diff options
author | Colin Watson <cjwatson@debian.org> | 2016-02-29 12:15:15 +0000 |
---|---|---|
committer | Colin Watson <cjwatson@debian.org> | 2016-02-29 12:15:15 +0000 |
commit | c52a95cc4754e6630c96fe65ae0c65eb41d2c590 (patch) | |
tree | 793395934013923b7b2426382c0676edcd4be3d4 /openbsd-compat | |
parent | eeff4de96f5d7365750dc56912c2c62b5c28db6b (diff) | |
parent | 72b061d4ba0f909501c595d709ea76e06b01e5c9 (diff) |
Import openssh_7.2p1.orig.tar.gz
Diffstat (limited to 'openbsd-compat')
-rw-r--r-- | openbsd-compat/bsd-misc.c | 8 | ||||
-rw-r--r-- | openbsd-compat/bsd-misc.h | 4 | ||||
-rw-r--r-- | openbsd-compat/bsd-poll.h | 4 | ||||
-rw-r--r-- | openbsd-compat/glob.c | 1 | ||||
-rw-r--r-- | openbsd-compat/glob.h | 8 | ||||
-rw-r--r-- | openbsd-compat/openbsd-compat.h | 1 | ||||
-rw-r--r-- | openbsd-compat/port-solaris.c | 136 | ||||
-rw-r--r-- | openbsd-compat/port-solaris.h | 6 | ||||
-rw-r--r-- | openbsd-compat/realpath.c | 61 |
9 files changed, 208 insertions, 21 deletions
diff --git a/openbsd-compat/bsd-misc.c b/openbsd-compat/bsd-misc.c index f7be415ec..2a788e47f 100644 --- a/openbsd-compat/bsd-misc.c +++ b/openbsd-compat/bsd-misc.c | |||
@@ -276,3 +276,11 @@ getpgid(pid_t pid) | |||
276 | return -1; | 276 | return -1; |
277 | } | 277 | } |
278 | #endif | 278 | #endif |
279 | |||
280 | #ifndef HAVE_PLEDGE | ||
281 | int | ||
282 | pledge(const char *promises, const char *paths[]) | ||
283 | { | ||
284 | return 0; | ||
285 | } | ||
286 | #endif | ||
diff --git a/openbsd-compat/bsd-misc.h b/openbsd-compat/bsd-misc.h index ff347a24b..0d81d1735 100644 --- a/openbsd-compat/bsd-misc.h +++ b/openbsd-compat/bsd-misc.h | |||
@@ -122,4 +122,8 @@ pid_t getpgid(pid_t); | |||
122 | # define krb5_free_error_message(a,b) do { } while(0) | 122 | # define krb5_free_error_message(a,b) do { } while(0) |
123 | #endif | 123 | #endif |
124 | 124 | ||
125 | #ifndef HAVE_PLEDGE | ||
126 | int pledge(const char *promises, const char *paths[]); | ||
127 | #endif | ||
128 | |||
125 | #endif /* _BSD_MISC_H */ | 129 | #endif /* _BSD_MISC_H */ |
diff --git a/openbsd-compat/bsd-poll.h b/openbsd-compat/bsd-poll.h index dcbb9ca40..17945f5b4 100644 --- a/openbsd-compat/bsd-poll.h +++ b/openbsd-compat/bsd-poll.h | |||
@@ -42,11 +42,11 @@ typedef unsigned int nfds_t; | |||
42 | #define POLLIN 0x0001 | 42 | #define POLLIN 0x0001 |
43 | #define POLLOUT 0x0004 | 43 | #define POLLOUT 0x0004 |
44 | #define POLLERR 0x0008 | 44 | #define POLLERR 0x0008 |
45 | #define POLLHUP 0x0010 | ||
46 | #define POLLNVAL 0x0020 | ||
45 | #if 0 | 47 | #if 0 |
46 | /* the following are currently not implemented */ | 48 | /* the following are currently not implemented */ |
47 | #define POLLPRI 0x0002 | 49 | #define POLLPRI 0x0002 |
48 | #define POLLHUP 0x0010 | ||
49 | #define POLLNVAL 0x0020 | ||
50 | #define POLLRDNORM 0x0040 | 50 | #define POLLRDNORM 0x0040 |
51 | #define POLLNORM POLLRDNORM | 51 | #define POLLNORM POLLRDNORM |
52 | #define POLLWRNORM POLLOUT | 52 | #define POLLWRNORM POLLOUT |
diff --git a/openbsd-compat/glob.c b/openbsd-compat/glob.c index 742b4b954..7c97e67f5 100644 --- a/openbsd-compat/glob.c +++ b/openbsd-compat/glob.c | |||
@@ -59,6 +59,7 @@ | |||
59 | */ | 59 | */ |
60 | 60 | ||
61 | #include "includes.h" | 61 | #include "includes.h" |
62 | #include "glob.h" | ||
62 | 63 | ||
63 | #include <sys/types.h> | 64 | #include <sys/types.h> |
64 | #include <sys/stat.h> | 65 | #include <sys/stat.h> |
diff --git a/openbsd-compat/glob.h b/openbsd-compat/glob.h index f8a7fa5ff..f069a05dc 100644 --- a/openbsd-compat/glob.h +++ b/openbsd-compat/glob.h | |||
@@ -42,11 +42,15 @@ | |||
42 | !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ | 42 | !defined(HAVE_DECL_GLOB_NOMATCH) || HAVE_DECL_GLOB_NOMATCH == 0 || \ |
43 | defined(BROKEN_GLOB) | 43 | defined(BROKEN_GLOB) |
44 | 44 | ||
45 | #ifndef _GLOB_H_ | 45 | #ifndef _COMPAT_GLOB_H_ |
46 | #define _GLOB_H_ | 46 | #define _COMPAT_GLOB_H_ |
47 | 47 | ||
48 | #include <sys/stat.h> | 48 | #include <sys/stat.h> |
49 | 49 | ||
50 | # define glob_t _ssh_compat_glob_t | ||
51 | # define glob(a, b, c, d) _ssh__compat_glob(a, b, c, d) | ||
52 | # define globfree(a) _ssh__compat_globfree(a) | ||
53 | |||
50 | struct stat; | 54 | struct stat; |
51 | typedef struct { | 55 | typedef struct { |
52 | int gl_pathc; /* Count of total paths so far. */ | 56 | int gl_pathc; /* Count of total paths so far. */ |
diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h index 1ff7114ef..8cc8a11b7 100644 --- a/openbsd-compat/openbsd-compat.h +++ b/openbsd-compat/openbsd-compat.h | |||
@@ -39,7 +39,6 @@ | |||
39 | /* OpenBSD function replacements */ | 39 | /* OpenBSD function replacements */ |
40 | #include "base64.h" | 40 | #include "base64.h" |
41 | #include "sigact.h" | 41 | #include "sigact.h" |
42 | #include "glob.h" | ||
43 | #include "readpassphrase.h" | 42 | #include "readpassphrase.h" |
44 | #include "vis.h" | 43 | #include "vis.h" |
45 | #include "getrrsetbyname.h" | 44 | #include "getrrsetbyname.h" |
diff --git a/openbsd-compat/port-solaris.c b/openbsd-compat/port-solaris.c index 25382f1c9..e36e412d7 100644 --- a/openbsd-compat/port-solaris.c +++ b/openbsd-compat/port-solaris.c | |||
@@ -227,3 +227,139 @@ solaris_set_default_project(struct passwd *pw) | |||
227 | } | 227 | } |
228 | } | 228 | } |
229 | #endif /* USE_SOLARIS_PROJECTS */ | 229 | #endif /* USE_SOLARIS_PROJECTS */ |
230 | |||
231 | #ifdef USE_SOLARIS_PRIVS | ||
232 | # ifdef HAVE_PRIV_H | ||
233 | # include <priv.h> | ||
234 | # endif | ||
235 | |||
236 | priv_set_t * | ||
237 | solaris_basic_privset(void) | ||
238 | { | ||
239 | priv_set_t *pset; | ||
240 | |||
241 | #ifdef HAVE_PRIV_BASICSET | ||
242 | if ((pset = priv_allocset()) == NULL) { | ||
243 | error("priv_allocset: %s", strerror(errno)); | ||
244 | return NULL; | ||
245 | } | ||
246 | priv_basicset(pset); | ||
247 | #else | ||
248 | if ((pset = priv_str_to_set("basic", ",", NULL)) == NULL) { | ||
249 | error("priv_str_to_set: %s", strerror(errno)); | ||
250 | return NULL; | ||
251 | } | ||
252 | #endif | ||
253 | return pset; | ||
254 | } | ||
255 | |||
256 | void | ||
257 | solaris_drop_privs_pinfo_net_fork_exec(void) | ||
258 | { | ||
259 | priv_set_t *pset = NULL, *npset = NULL; | ||
260 | |||
261 | /* | ||
262 | * Note: this variant avoids dropping DAC filesystem rights, in case | ||
263 | * the process calling it is running as root and should have the | ||
264 | * ability to read/write/chown any file on the system. | ||
265 | * | ||
266 | * We start with the basic set, then *add* the DAC rights to it while | ||
267 | * taking away other parts of BASIC we don't need. Then we intersect | ||
268 | * this with our existing PERMITTED set. In this way we keep any | ||
269 | * DAC rights we had before, while otherwise reducing ourselves to | ||
270 | * the minimum set of privileges we need to proceed. | ||
271 | * | ||
272 | * This also means we drop any other parts of "root" that we don't | ||
273 | * need (e.g. the ability to kill any process, create new device nodes | ||
274 | * etc etc). | ||
275 | */ | ||
276 | |||
277 | if ((pset = priv_allocset()) == NULL) | ||
278 | fatal("priv_allocset: %s", strerror(errno)); | ||
279 | if ((npset = solaris_basic_privset()) == NULL) | ||
280 | fatal("solaris_basic_privset: %s", strerror(errno)); | ||
281 | |||
282 | if (priv_addset(npset, PRIV_FILE_CHOWN) != 0 || | ||
283 | priv_addset(npset, PRIV_FILE_DAC_READ) != 0 || | ||
284 | priv_addset(npset, PRIV_FILE_DAC_SEARCH) != 0 || | ||
285 | priv_addset(npset, PRIV_FILE_DAC_WRITE) != 0 || | ||
286 | priv_addset(npset, PRIV_FILE_OWNER) != 0) | ||
287 | fatal("priv_addset: %s", strerror(errno)); | ||
288 | |||
289 | if (priv_delset(npset, PRIV_FILE_LINK_ANY) != 0 || | ||
290 | #ifdef PRIV_NET_ACCESS | ||
291 | priv_delset(npset, PRIV_NET_ACCESS) != 0 || | ||
292 | #endif | ||
293 | priv_delset(npset, PRIV_PROC_EXEC) != 0 || | ||
294 | priv_delset(npset, PRIV_PROC_FORK) != 0 || | ||
295 | priv_delset(npset, PRIV_PROC_INFO) != 0 || | ||
296 | priv_delset(npset, PRIV_PROC_SESSION) != 0) | ||
297 | fatal("priv_delset: %s", strerror(errno)); | ||
298 | |||
299 | if (getppriv(PRIV_PERMITTED, pset) != 0) | ||
300 | fatal("getppriv: %s", strerror(errno)); | ||
301 | |||
302 | priv_intersect(pset, npset); | ||
303 | |||
304 | if (setppriv(PRIV_SET, PRIV_PERMITTED, npset) != 0 || | ||
305 | setppriv(PRIV_SET, PRIV_LIMIT, npset) != 0 || | ||
306 | setppriv(PRIV_SET, PRIV_INHERITABLE, npset) != 0) | ||
307 | fatal("setppriv: %s", strerror(errno)); | ||
308 | |||
309 | priv_freeset(pset); | ||
310 | priv_freeset(npset); | ||
311 | } | ||
312 | |||
313 | void | ||
314 | solaris_drop_privs_root_pinfo_net(void) | ||
315 | { | ||
316 | priv_set_t *pset = NULL; | ||
317 | |||
318 | /* Start with "basic" and drop everything we don't need. */ | ||
319 | if ((pset = solaris_basic_privset()) == NULL) | ||
320 | fatal("solaris_basic_privset: %s", strerror(errno)); | ||
321 | |||
322 | if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 || | ||
323 | #ifdef PRIV_NET_ACCESS | ||
324 | priv_delset(pset, PRIV_NET_ACCESS) != 0 || | ||
325 | #endif | ||
326 | priv_delset(pset, PRIV_PROC_INFO) != 0 || | ||
327 | priv_delset(pset, PRIV_PROC_SESSION) != 0) | ||
328 | fatal("priv_delset: %s", strerror(errno)); | ||
329 | |||
330 | if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 || | ||
331 | setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 || | ||
332 | setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0) | ||
333 | fatal("setppriv: %s", strerror(errno)); | ||
334 | |||
335 | priv_freeset(pset); | ||
336 | } | ||
337 | |||
338 | void | ||
339 | solaris_drop_privs_root_pinfo_net_exec(void) | ||
340 | { | ||
341 | priv_set_t *pset = NULL; | ||
342 | |||
343 | |||
344 | /* Start with "basic" and drop everything we don't need. */ | ||
345 | if ((pset = solaris_basic_privset()) == NULL) | ||
346 | fatal("solaris_basic_privset: %s", strerror(errno)); | ||
347 | |||
348 | if (priv_delset(pset, PRIV_FILE_LINK_ANY) != 0 || | ||
349 | #ifdef PRIV_NET_ACCESS | ||
350 | priv_delset(pset, PRIV_NET_ACCESS) != 0 || | ||
351 | #endif | ||
352 | priv_delset(pset, PRIV_PROC_EXEC) != 0 || | ||
353 | priv_delset(pset, PRIV_PROC_INFO) != 0 || | ||
354 | priv_delset(pset, PRIV_PROC_SESSION) != 0) | ||
355 | fatal("priv_delset: %s", strerror(errno)); | ||
356 | |||
357 | if (setppriv(PRIV_SET, PRIV_PERMITTED, pset) != 0 || | ||
358 | setppriv(PRIV_SET, PRIV_LIMIT, pset) != 0 || | ||
359 | setppriv(PRIV_SET, PRIV_INHERITABLE, pset) != 0) | ||
360 | fatal("setppriv: %s", strerror(errno)); | ||
361 | |||
362 | priv_freeset(pset); | ||
363 | } | ||
364 | |||
365 | #endif | ||
diff --git a/openbsd-compat/port-solaris.h b/openbsd-compat/port-solaris.h index cd442e78b..3a41ea8cd 100644 --- a/openbsd-compat/port-solaris.h +++ b/openbsd-compat/port-solaris.h | |||
@@ -26,5 +26,11 @@ void solaris_contract_pre_fork(void); | |||
26 | void solaris_contract_post_fork_child(void); | 26 | void solaris_contract_post_fork_child(void); |
27 | void solaris_contract_post_fork_parent(pid_t pid); | 27 | void solaris_contract_post_fork_parent(pid_t pid); |
28 | void solaris_set_default_project(struct passwd *); | 28 | void solaris_set_default_project(struct passwd *); |
29 | # ifdef USE_SOLARIS_PRIVS | ||
30 | priv_set_t *solaris_basic_privset(void); | ||
31 | void solaris_drop_privs_pinfo_net_fork_exec(void); | ||
32 | void solaris_drop_privs_root_pinfo_net(void); | ||
33 | void solaris_drop_privs_root_pinfo_net_exec(void); | ||
34 | # endif /* USE_SOLARIS_PRIVS */ | ||
29 | 35 | ||
30 | #endif | 36 | #endif |
diff --git a/openbsd-compat/realpath.c b/openbsd-compat/realpath.c index ba4cea938..a2f090e55 100644 --- a/openbsd-compat/realpath.c +++ b/openbsd-compat/realpath.c | |||
@@ -1,4 +1,4 @@ | |||
1 | /* $OpenBSD: realpath.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */ | 1 | /* $OpenBSD: realpath.c,v 1.20 2015/10/13 20:55:37 millert Exp $ */ |
2 | /* | 2 | /* |
3 | * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru> | 3 | * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru> |
4 | * | 4 | * |
@@ -42,6 +42,13 @@ | |||
42 | #include <stddef.h> | 42 | #include <stddef.h> |
43 | #include <string.h> | 43 | #include <string.h> |
44 | #include <unistd.h> | 44 | #include <unistd.h> |
45 | #include <limits.h> | ||
46 | |||
47 | #ifndef SYMLOOP_MAX | ||
48 | # define SYMLOOP_MAX 32 | ||
49 | #endif | ||
50 | |||
51 | /* A slightly modified copy of this file exists in libexec/ld.so */ | ||
45 | 52 | ||
46 | /* | 53 | /* |
47 | * char *realpath(const char *path, char resolved[PATH_MAX]); | 54 | * char *realpath(const char *path, char resolved[PATH_MAX]); |
@@ -51,16 +58,30 @@ | |||
51 | * in which case the path which caused trouble is left in (resolved). | 58 | * in which case the path which caused trouble is left in (resolved). |
52 | */ | 59 | */ |
53 | char * | 60 | char * |
54 | realpath(const char *path, char resolved[PATH_MAX]) | 61 | realpath(const char *path, char *resolved) |
55 | { | 62 | { |
56 | struct stat sb; | 63 | struct stat sb; |
57 | char *p, *q, *s; | 64 | char *p, *q, *s; |
58 | size_t left_len, resolved_len; | 65 | size_t left_len, resolved_len; |
59 | unsigned symlinks; | 66 | unsigned symlinks; |
60 | int serrno, slen; | 67 | int serrno, slen, mem_allocated; |
61 | char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; | 68 | char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX]; |
62 | 69 | ||
70 | if (path[0] == '\0') { | ||
71 | errno = ENOENT; | ||
72 | return (NULL); | ||
73 | } | ||
74 | |||
63 | serrno = errno; | 75 | serrno = errno; |
76 | |||
77 | if (resolved == NULL) { | ||
78 | resolved = malloc(PATH_MAX); | ||
79 | if (resolved == NULL) | ||
80 | return (NULL); | ||
81 | mem_allocated = 1; | ||
82 | } else | ||
83 | mem_allocated = 0; | ||
84 | |||
64 | symlinks = 0; | 85 | symlinks = 0; |
65 | if (path[0] == '/') { | 86 | if (path[0] == '/') { |
66 | resolved[0] = '/'; | 87 | resolved[0] = '/'; |
@@ -71,7 +92,10 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
71 | left_len = strlcpy(left, path + 1, sizeof(left)); | 92 | left_len = strlcpy(left, path + 1, sizeof(left)); |
72 | } else { | 93 | } else { |
73 | if (getcwd(resolved, PATH_MAX) == NULL) { | 94 | if (getcwd(resolved, PATH_MAX) == NULL) { |
74 | strlcpy(resolved, ".", PATH_MAX); | 95 | if (mem_allocated) |
96 | free(resolved); | ||
97 | else | ||
98 | strlcpy(resolved, ".", PATH_MAX); | ||
75 | return (NULL); | 99 | return (NULL); |
76 | } | 100 | } |
77 | resolved_len = strlen(resolved); | 101 | resolved_len = strlen(resolved); |
@@ -79,7 +103,7 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
79 | } | 103 | } |
80 | if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { | 104 | if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) { |
81 | errno = ENAMETOOLONG; | 105 | errno = ENAMETOOLONG; |
82 | return (NULL); | 106 | goto err; |
83 | } | 107 | } |
84 | 108 | ||
85 | /* | 109 | /* |
@@ -94,7 +118,7 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
94 | s = p ? p : left + left_len; | 118 | s = p ? p : left + left_len; |
95 | if (s - left >= (ptrdiff_t)sizeof(next_token)) { | 119 | if (s - left >= (ptrdiff_t)sizeof(next_token)) { |
96 | errno = ENAMETOOLONG; | 120 | errno = ENAMETOOLONG; |
97 | return (NULL); | 121 | goto err; |
98 | } | 122 | } |
99 | memcpy(next_token, left, s - left); | 123 | memcpy(next_token, left, s - left); |
100 | next_token[s - left] = '\0'; | 124 | next_token[s - left] = '\0'; |
@@ -104,7 +128,7 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
104 | if (resolved[resolved_len - 1] != '/') { | 128 | if (resolved[resolved_len - 1] != '/') { |
105 | if (resolved_len + 1 >= PATH_MAX) { | 129 | if (resolved_len + 1 >= PATH_MAX) { |
106 | errno = ENAMETOOLONG; | 130 | errno = ENAMETOOLONG; |
107 | return (NULL); | 131 | goto err; |
108 | } | 132 | } |
109 | resolved[resolved_len++] = '/'; | 133 | resolved[resolved_len++] = '/'; |
110 | resolved[resolved_len] = '\0'; | 134 | resolved[resolved_len] = '\0'; |
@@ -135,23 +159,23 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
135 | resolved_len = strlcat(resolved, next_token, PATH_MAX); | 159 | resolved_len = strlcat(resolved, next_token, PATH_MAX); |
136 | if (resolved_len >= PATH_MAX) { | 160 | if (resolved_len >= PATH_MAX) { |
137 | errno = ENAMETOOLONG; | 161 | errno = ENAMETOOLONG; |
138 | return (NULL); | 162 | goto err; |
139 | } | 163 | } |
140 | if (lstat(resolved, &sb) != 0) { | 164 | if (lstat(resolved, &sb) != 0) { |
141 | if (errno == ENOENT && p == NULL) { | 165 | if (errno == ENOENT && p == NULL) { |
142 | errno = serrno; | 166 | errno = serrno; |
143 | return (resolved); | 167 | return (resolved); |
144 | } | 168 | } |
145 | return (NULL); | 169 | goto err; |
146 | } | 170 | } |
147 | if (S_ISLNK(sb.st_mode)) { | 171 | if (S_ISLNK(sb.st_mode)) { |
148 | if (symlinks++ > MAXSYMLINKS) { | 172 | if (symlinks++ > SYMLOOP_MAX) { |
149 | errno = ELOOP; | 173 | errno = ELOOP; |
150 | return (NULL); | 174 | goto err; |
151 | } | 175 | } |
152 | slen = readlink(resolved, symlink, sizeof(symlink) - 1); | 176 | slen = readlink(resolved, symlink, sizeof(symlink) - 1); |
153 | if (slen < 0) | 177 | if (slen < 0) |
154 | return (NULL); | 178 | goto err; |
155 | symlink[slen] = '\0'; | 179 | symlink[slen] = '\0'; |
156 | if (symlink[0] == '/') { | 180 | if (symlink[0] == '/') { |
157 | resolved[1] = 0; | 181 | resolved[1] = 0; |
@@ -174,15 +198,15 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
174 | if (slen + 1 >= | 198 | if (slen + 1 >= |
175 | (ptrdiff_t)sizeof(symlink)) { | 199 | (ptrdiff_t)sizeof(symlink)) { |
176 | errno = ENAMETOOLONG; | 200 | errno = ENAMETOOLONG; |
177 | return (NULL); | 201 | goto err; |
178 | } | 202 | } |
179 | symlink[slen] = '/'; | 203 | symlink[slen] = '/'; |
180 | symlink[slen + 1] = 0; | 204 | symlink[slen + 1] = 0; |
181 | } | 205 | } |
182 | left_len = strlcat(symlink, left, sizeof(left)); | 206 | left_len = strlcat(symlink, left, sizeof(symlink)); |
183 | if (left_len >= sizeof(left)) { | 207 | if (left_len >= sizeof(symlink)) { |
184 | errno = ENAMETOOLONG; | 208 | errno = ENAMETOOLONG; |
185 | return (NULL); | 209 | goto err; |
186 | } | 210 | } |
187 | } | 211 | } |
188 | left_len = strlcpy(left, symlink, sizeof(left)); | 212 | left_len = strlcpy(left, symlink, sizeof(left)); |
@@ -196,5 +220,10 @@ realpath(const char *path, char resolved[PATH_MAX]) | |||
196 | if (resolved_len > 1 && resolved[resolved_len - 1] == '/') | 220 | if (resolved_len > 1 && resolved[resolved_len - 1] == '/') |
197 | resolved[resolved_len - 1] = '\0'; | 221 | resolved[resolved_len - 1] = '\0'; |
198 | return (resolved); | 222 | return (resolved); |
223 | |||
224 | err: | ||
225 | if (mem_allocated) | ||
226 | free(resolved); | ||
227 | return (NULL); | ||
199 | } | 228 | } |
200 | #endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ | 229 | #endif /* !defined(HAVE_REALPATH) || defined(BROKEN_REALPATH) */ |