Give systrace its own version of realpath() that does what it wants,
call it intercept_realpath(). Unbreaks systrace.
This commit is contained in:
parent
e77db80a44
commit
9d002bc47d
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: intercept.c,v 1.25 2005/06/27 17:11:20 elad Exp $ */
|
||||
/* $NetBSD: intercept.c,v 1.26 2005/12/31 12:33:41 elad Exp $ */
|
||||
/* $OpenBSD: intercept.c,v 1.29 2002/08/28 03:30:27 itojun Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
|
@ -30,7 +30,7 @@
|
|||
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: intercept.c,v 1.25 2005/06/27 17:11:20 elad Exp $");
|
||||
__RCSID("$NetBSD: intercept.c,v 1.26 2005/12/31 12:33:41 elad Exp $");
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/param.h>
|
||||
|
@ -672,7 +672,7 @@ normalize_filename(int fd, pid_t pid, char *name, int userp)
|
|||
|
||||
/* If realpath fails then the filename does not exist,
|
||||
* or we are supposed to not resolve the last component */
|
||||
if (realpath(cwd, rcwd) == NULL) {
|
||||
if (intercept_realpath(cwd, rcwd) == NULL) {
|
||||
char *dir, *file;
|
||||
struct stat st;
|
||||
|
||||
|
@ -691,7 +691,7 @@ normalize_filename(int fd, pid_t pid, char *name, int userp)
|
|||
goto error;
|
||||
|
||||
/* So, try again */
|
||||
if (realpath(dir, rcwd) == NULL) {
|
||||
if (intercept_realpath(dir, rcwd) == NULL) {
|
||||
failed = 1;
|
||||
goto out;
|
||||
}
|
||||
|
@ -990,3 +990,143 @@ intercept_policy_free(int policynr)
|
|||
{
|
||||
(*intercept_pfreecb)(policynr, intercept_pfreearg);
|
||||
}
|
||||
|
||||
char *
|
||||
intercept_realpath(const char *path, char *resolved)
|
||||
{
|
||||
struct stat sb;
|
||||
int idx = 0, n, nlnk = 0, serrno = errno;
|
||||
const char *q;
|
||||
char *p, wbuf[2][MAXPATHLEN];
|
||||
size_t len;
|
||||
|
||||
/*
|
||||
* Build real path one by one with paying an attention to .,
|
||||
* .. and symbolic link.
|
||||
*/
|
||||
|
||||
/*
|
||||
* `p' is where we'll put a new component with prepending
|
||||
* a delimiter.
|
||||
*/
|
||||
p = resolved;
|
||||
|
||||
if (*path == 0) {
|
||||
*p = 0;
|
||||
errno = ENOENT;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* If relative path, start from current working directory. */
|
||||
if (*path != '/') {
|
||||
if (getcwd(resolved, MAXPATHLEN) == NULL) {
|
||||
p[0] = '.';
|
||||
p[1] = 0;
|
||||
return (NULL);
|
||||
}
|
||||
len = strlen(resolved);
|
||||
if (len > 1)
|
||||
p += len;
|
||||
}
|
||||
|
||||
loop:
|
||||
/* Skip any slash. */
|
||||
while (*path == '/')
|
||||
path++;
|
||||
|
||||
if (*path == 0) {
|
||||
if (p == resolved)
|
||||
*p++ = '/';
|
||||
*p = 0;
|
||||
return (resolved);
|
||||
}
|
||||
|
||||
/* Find the end of this component. */
|
||||
q = path;
|
||||
do
|
||||
q++;
|
||||
while (*q != '/' && *q != 0);
|
||||
|
||||
/* Test . or .. */
|
||||
if (path[0] == '.') {
|
||||
if (q - path == 1) {
|
||||
path = q;
|
||||
goto loop;
|
||||
}
|
||||
if (path[1] == '.' && q - path == 2) {
|
||||
/* Trim the last component. */
|
||||
if (p != resolved)
|
||||
while (*--p != '/')
|
||||
;
|
||||
path = q;
|
||||
goto loop;
|
||||
}
|
||||
}
|
||||
|
||||
/* Append this component. */
|
||||
if (p - resolved + 1 + q - path + 1 > MAXPATHLEN) {
|
||||
errno = ENAMETOOLONG;
|
||||
if (p == resolved)
|
||||
*p++ = '/';
|
||||
*p = 0;
|
||||
return (NULL);
|
||||
}
|
||||
p[0] = '/';
|
||||
memcpy(&p[1], path,
|
||||
/* LINTED We know q > path. */
|
||||
q - path);
|
||||
p[1 + q - path] = 0;
|
||||
|
||||
/*
|
||||
* If this component is a symlink, toss it and prepend link
|
||||
* target to unresolved path.
|
||||
*/
|
||||
if (lstat(resolved, &sb) == -1) {
|
||||
/* Allow nonexistent component if this is the last one. */
|
||||
while (*q == '/')
|
||||
q++;
|
||||
|
||||
if (*q == 0 && errno == ENOENT) {
|
||||
errno = serrno;
|
||||
return (resolved);
|
||||
}
|
||||
|
||||
return (NULL);
|
||||
}
|
||||
if (S_ISLNK(sb.st_mode)) {
|
||||
if (nlnk++ >= MAXSYMLINKS) {
|
||||
errno = ELOOP;
|
||||
return (NULL);
|
||||
}
|
||||
n = readlink(resolved, wbuf[idx], sizeof(wbuf[0]) - 1);
|
||||
if (n < 0)
|
||||
return (NULL);
|
||||
if (n == 0) {
|
||||
errno = ENOENT;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Append unresolved path to link target and switch to it. */
|
||||
if (n + (len = strlen(q)) + 1 > sizeof(wbuf[0])) {
|
||||
errno = ENAMETOOLONG;
|
||||
return (NULL);
|
||||
}
|
||||
memcpy(&wbuf[idx][n], q, len + 1);
|
||||
path = wbuf[idx];
|
||||
idx ^= 1;
|
||||
|
||||
/* If absolute symlink, start from root. */
|
||||
if (*path == '/')
|
||||
p = resolved;
|
||||
goto loop;
|
||||
}
|
||||
if (*q == '/' && !S_ISDIR(sb.st_mode)) {
|
||||
errno = ENOTDIR;
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
/* Advance both resolved and unresolved path. */
|
||||
p += 1 + q - path;
|
||||
path = q;
|
||||
goto loop;
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: intercept.h,v 1.17 2005/06/27 17:11:20 elad Exp $ */
|
||||
/* $NetBSD: intercept.h,v 1.18 2005/12/31 12:33:41 elad Exp $ */
|
||||
/* $OpenBSD: intercept.h,v 1.11 2002/08/04 04:15:50 provos Exp $ */
|
||||
/*
|
||||
* Copyright 2002 Niels Provos <provos@citi.umich.edu>
|
||||
|
@ -203,4 +203,6 @@ void intercept_newimage(int, pid_t, int, const char *, char *,
|
|||
|
||||
int intercept_isvalidsystemcall(char *, char *);
|
||||
|
||||
char *intercept_realpath(const char *, char *);
|
||||
|
||||
#endif /* _INTERCEPT_H_ */
|
||||
|
|
Loading…
Reference in New Issue