Skip to content

Commit

Permalink
OS-3927 lxbrand in-kernel unlink(2) and unlinkat(2)
Browse files Browse the repository at this point in the history
OS-3928 lxbrand in-kernel symlink(2) and symlinkat(2)
OS-3988 lxbrand in-kernel readlinkat(2) and readlink(2)
Reviewed by: Patrick Mooney <patrick.mooney@joyent.com>
Approved by: Patrick Mooney <patrick.mooney@joyent.com>
  • Loading branch information
jjelinek committed Sep 16, 2016
1 parent 41c2980 commit abec4d3
Show file tree
Hide file tree
Showing 9 changed files with 135 additions and 213 deletions.
167 changes: 0 additions & 167 deletions usr/src/lib/brand/lx/lx_brand/common/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,116 +72,10 @@ install_checkpath(uintptr_t p1)
return (-errno);
}

/*
* Convert linux LX_AT_* flags to solaris AT_* flags but skip verifying allowed
* flags have been passed. This also allows EACCESS/REMOVEDIR to be translated
* correctly since on linux they have the same value.
*
* Some code can actually pass in other bits in the flag. We may have to simply
* ignore these, as indicated by the enforce parameter. See lx_fchmodat for
* another example of this type of behavior.
*/
static int
ltos_at_flag(int lflag, int allow, boolean_t enforce)
{
int sflag = 0;

if ((lflag & LX_AT_EACCESS) && (allow & AT_EACCESS)) {
lflag &= ~LX_AT_EACCESS;
sflag |= AT_EACCESS;
}

if ((lflag & LX_AT_REMOVEDIR) && (allow & AT_REMOVEDIR)) {
lflag &= ~LX_AT_REMOVEDIR;
sflag |= AT_REMOVEDIR;
}

if ((lflag & LX_AT_SYMLINK_NOFOLLOW) && (allow & AT_SYMLINK_NOFOLLOW)) {
lflag &= ~LX_AT_SYMLINK_NOFOLLOW;
sflag |= AT_SYMLINK_NOFOLLOW;
}

/* right now solaris doesn't have a _FOLLOW flag, so use a fake one */
if ((lflag & LX_AT_SYMLINK_FOLLOW) && (allow & LX_AT_SYMLINK_FOLLOW)) {
lflag &= ~LX_AT_SYMLINK_FOLLOW;
sflag |= LX_AT_SYMLINK_FOLLOW;
}

/* If lflag is not zero than some flags did not hit the above code. */
if (enforce && lflag)
return (-EINVAL);

return (sflag);
}


/*
* Miscellaneous file-related system calls.
*/

/*
* On Linux, an unlink of a directory returns EISDIR, not EPERM.
*/
long
lx_unlink(uintptr_t p)
{
char *pathname = (char *)p;
struct stat64 statbuf;

if ((lstat64(pathname, &statbuf) == 0) && S_ISDIR(statbuf.st_mode))
return (-EISDIR);

/*
* Some versions of the zone's /dev/log setup code (e.g. syslog-ng) get
* cranky if they can't cleanup /dev/log so we lie and tell them they
* succeeded.
*/
if (pathname != NULL) {
char p[MAXPATHLEN];

if (uucopystr((void *)pathname, p, sizeof (p)) < 0)
return (-errno);
if (strcmp(p, "/dev/log") == 0)
return (0);
}

return (unlink(pathname) ? -errno : 0);
}

long
lx_unlinkat(uintptr_t ext1, uintptr_t p1, uintptr_t p2)
{
int atfd = (int)ext1;
char *pathname = (char *)p1;
int flag = (int)p2;
struct stat64 statbuf;

if (atfd == LX_AT_FDCWD)
atfd = AT_FDCWD;

flag = ltos_at_flag(flag, AT_REMOVEDIR, B_TRUE);
if (flag < 0)
return (-EINVAL);

if (!(flag & AT_REMOVEDIR)) {
/* Behave like unlink() */
if ((fstatat64(atfd, pathname, &statbuf, AT_SYMLINK_NOFOLLOW) ==
0) && S_ISDIR(statbuf.st_mode))
return (-EISDIR);

if (pathname != NULL) {
char p[MAXPATHLEN];

if (uucopystr((void *)pathname, p, sizeof (p)) < 0)
return (-errno);
if (strcmp(p, "/dev/log") == 0)
return (0);
}
}

return (unlinkat(atfd, pathname, flag) ? -errno : 0);
}

/*
* fsync() and fdatasync() - On Illumos, these calls translate into a common
* fdsync() syscall with a different parameter. fsync is handled in the
Expand Down Expand Up @@ -462,64 +356,3 @@ lx_mknodat(uintptr_t ext1, uintptr_t p1, uintptr_t p2, uintptr_t p3)

return (lx_mknod((uintptr_t)pathbuf, p2, p3));
}

long
lx_symlinkat(uintptr_t p1, uintptr_t ext1, uintptr_t p2)
{
int atfd = (int)ext1;
char pathbuf[MAXPATHLEN];
int ret;

ret = getpathat(atfd, p2, pathbuf, sizeof (pathbuf));
if (ret < 0) {
if (ret == -EBADF) {
/*
* Try to figure out correct Linux errno. We know path
* is relative. Check if we have a fd for a dir which
* has been removed.
*/
if (atfd != -1 && lx_fd_to_path(atfd, pathbuf,
sizeof (pathbuf)) == NULL)
ret = -ENOENT;
}
return (ret);
}

return (symlink((char *)p1, pathbuf) ? -errno : 0);
}

long
lx_readlink(uintptr_t p1, uintptr_t p2, uintptr_t p3)
{
int ret;

if ((size_t)p3 <= 0)
return (-EINVAL);

ret = readlink((char *)p1, (char *)p2, (size_t)p3);
if (ret < 0)
return (-errno);

return (ret);
}

long
lx_readlinkat(uintptr_t ext1, uintptr_t p1, uintptr_t p2, uintptr_t p3)
{
int atfd = (int)ext1;
char pathbuf[MAXPATHLEN];
int ret;

if ((size_t)p3 <= 0)
return (-EINVAL);

ret = getpathat(atfd, p1, pathbuf, sizeof (pathbuf));
if (ret < 0)
return (ret);

ret = readlink(pathbuf, (char *)p2, (size_t)p3);
if (ret < 0)
return (-errno);

return (ret);
}
24 changes: 12 additions & 12 deletions usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
Original file line number Diff line number Diff line change
Expand Up @@ -1098,9 +1098,9 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_rmdir, /* 84: rmdir */
lx_creat, /* 85: creat */
NULL, /* 86: link */
lx_unlink, /* 87: unlink */
lx_symlink, /* 88: symlink */
lx_readlink, /* 89: readlink */
NULL, /* 87: unlink */
NULL, /* 88: symlink */
NULL, /* 89: readlink */
NULL, /* 90: chmod */
NULL, /* 91: fchmod */
NULL, /* 92: chown */
Expand Down Expand Up @@ -1274,11 +1274,11 @@ static lx_syscall_handler_t lx_handlers[] = {
NULL, /* 260: fchownat */
lx_futimesat, /* 261: futimesat */
NULL, /* 262: fstatat64 */
lx_unlinkat, /* 263: unlinkat */
NULL, /* 263: unlinkat */
lx_renameat, /* 264: renameat */
NULL, /* 265: linkat */
lx_symlinkat, /* 266: symlinkat */
lx_readlinkat, /* 267: readlinkat */
NULL, /* 266: symlinkat */
NULL, /* 267: readlinkat */
NULL, /* 268: fchmodat */
NULL, /* 269: faccessat */
NULL, /* 270: pselect6 */
Expand Down Expand Up @@ -1352,7 +1352,7 @@ static lx_syscall_handler_t lx_handlers[] = {
NULL, /* 7: waitpid */
lx_creat, /* 8: creat */
NULL, /* 9: link */
lx_unlink, /* 10: unlink */
NULL, /* 10: unlink */
lx_execve, /* 11: execve */
lx_chdir, /* 12: chdir */
NULL, /* 13: time */
Expand Down Expand Up @@ -1425,9 +1425,9 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_getgroups16, /* 80: getgroups16 */
lx_setgroups16, /* 81: setgroups16 */
NULL, /* 82: select */
lx_symlink, /* 83: symlink */
NULL, /* 83: symlink */
NULL, /* 84: oldlstat */
lx_readlink, /* 85: readlink */
NULL, /* 85: readlink */
NULL, /* 86: uselib */
NULL, /* 87: swapon */
lx_reboot, /* 88: reboot */
Expand Down Expand Up @@ -1643,11 +1643,11 @@ static lx_syscall_handler_t lx_handlers[] = {
NULL, /* 298: fchownat */
lx_futimesat, /* 299: futimesat */
NULL, /* 300: fstatat64 */
lx_unlinkat, /* 301: unlinkat */
NULL, /* 301: unlinkat */
lx_renameat, /* 302: renameat */
NULL, /* 303: linkat */
lx_symlinkat, /* 304: symlinkat */
lx_readlinkat, /* 305: readlinkat */
NULL, /* 304: symlinkat */
NULL, /* 305: readlinkat */
NULL, /* 306: fchmodat */
NULL, /* 307: faccessat */
NULL, /* 308: pselect6 */
Expand Down
9 changes: 0 additions & 9 deletions usr/src/lib/brand/lx/lx_brand/common/misc.c
Original file line number Diff line number Diff line change
Expand Up @@ -632,15 +632,6 @@ lx_stime(const time_t *tp)
return ((r == -1) ? -errno : r);
}

long
lx_symlink(const char *name1, const char *name2)
{
int r;

r = symlink(name1, name2);
return ((r == -1) ? -errno : r);
}

long
lx_utimes(const char *path, const struct timeval times[2])
{
Expand Down
8 changes: 1 addition & 7 deletions usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,21 +48,17 @@ extern long lx_mknodat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
extern long lx_futimesat(uintptr_t, uintptr_t, uintptr_t);
extern long lx_utimensat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
extern long lx_fstatat64(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
extern long lx_unlinkat(uintptr_t, uintptr_t, uintptr_t);
extern long lx_renameat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
extern long lx_symlinkat(uintptr_t, uintptr_t, uintptr_t);
extern long lx_readlinkat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);

extern long lx_stat(uintptr_t, uintptr_t);
extern long lx_fstat(uintptr_t, uintptr_t);
extern long lx_lstat(uintptr_t, uintptr_t);
extern long lx_stat64(uintptr_t, uintptr_t);
extern long lx_fstat64(uintptr_t, uintptr_t);
extern long lx_renameat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
extern long lx_lstat64(uintptr_t, uintptr_t);
extern long lx_fcntl(uintptr_t, uintptr_t, uintptr_t);
extern long lx_fcntl64(uintptr_t, uintptr_t, uintptr_t);
extern long lx_flock(uintptr_t, uintptr_t);
extern long lx_readlink(uintptr_t, uintptr_t, uintptr_t);
extern long lx_readdir(uintptr_t, uintptr_t, uintptr_t);
extern long lx_execve(uintptr_t, uintptr_t, uintptr_t);
extern long lx_ioctl(uintptr_t, uintptr_t, uintptr_t);
Expand Down Expand Up @@ -107,7 +103,6 @@ extern long lx_ftruncate64(uintptr_t, uintptr_t, uintptr_t);
extern long lx_sysctl(uintptr_t);
extern long lx_fsync(uintptr_t);
extern long lx_fdatasync(uintptr_t);
extern long lx_unlink(uintptr_t);
extern long lx_rmdir(uintptr_t);
extern long lx_rename(uintptr_t, uintptr_t);
extern long lx_utime(uintptr_t, uintptr_t);
Expand Down Expand Up @@ -242,7 +237,6 @@ extern long lx_shmdt(char *);
extern long lx_signalfd(int, uintptr_t, size_t);
extern long lx_signalfd4(int, uintptr_t, size_t, int);
extern long lx_stime(const time_t *);
extern long lx_symlink(const char *, const char *);
extern long lx_syslog(int, char *, int);
extern long lx_timerfd_create(int, int);
extern long lx_timerfd_settime(int, int,
Expand Down
24 changes: 12 additions & 12 deletions usr/src/uts/common/brand/lx/os/lx_syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -531,7 +531,7 @@ lx_sysent_t lx_sysent32[] = {
{"waitpid", lx_waitpid, 0, 3}, /* 7 */
{"creat", NULL, 0, 2}, /* 8 */
{"link", lx_link, 0, 2}, /* 9 */
{"unlink", NULL, 0, 1}, /* 10 */
{"unlink", lx_unlink, 0, 1}, /* 10 */
{"execve", NULL, 0, 3}, /* 11 */
{"chdir", NULL, 0, 1}, /* 12 */
{"time", lx_time, 0, 1}, /* 13 */
Expand Down Expand Up @@ -604,9 +604,9 @@ lx_sysent_t lx_sysent32[] = {
{"getgroups16", NULL, 0, 2}, /* 80 */
{"setgroups16", NULL, 0, 2}, /* 81 */
{"select", NULL, NOSYS_OBSOLETE, 0}, /* 82 */
{"symlink", NULL, 0, 2}, /* 83 */
{"symlink", lx_symlink, 0, 2}, /* 83 */
{"oldlstat", NULL, NOSYS_OBSOLETE, 0}, /* 84 */
{"readlink", NULL, 0, 3}, /* 85 */
{"readlink", lx_readlink, 0, 3}, /* 85 */
{"uselib", NULL, NOSYS_KERNEL, 0}, /* 86 */
{"swapon", NULL, NOSYS_KERNEL, 0}, /* 87 */
{"reboot", NULL, 0, 4}, /* 88 */
Expand Down Expand Up @@ -826,11 +826,11 @@ lx_sysent_t lx_sysent32[] = {
{"fchownat", lx_fchownat, 0, 5}, /* 298 */
{"futimesat", NULL, 0, 3}, /* 299 */
{"fstatat64", lx_fstatat64, 0, 4}, /* 300 */
{"unlinkat", NULL, 0, 3}, /* 301 */
{"unlinkat", lx_unlinkat, 0, 3}, /* 301 */
{"renameat", NULL, 0, 4}, /* 302 */
{"linkat", lx_linkat, 0, 5}, /* 303 */
{"symlinkat", NULL, 0, 3}, /* 304 */
{"readlinkat", NULL, 0, 4}, /* 305 */
{"symlinkat", lx_symlinkat, 0, 3}, /* 304 */
{"readlinkat", lx_readlinkat, 0, 4}, /* 305 */
{"fchmodat", lx_fchmodat, 0, 3}, /* 306 */
{"faccessat", lx_faccessat, 0, 4}, /* 307 */
{"pselect6", lx_pselect, LX_SYS_EBPARG6, 6}, /* 308 */
Expand Down Expand Up @@ -979,9 +979,9 @@ lx_sysent_t lx_sysent64[] = {
{"rmdir", NULL, 0, 1}, /* 84 */
{"creat", NULL, 0, 2}, /* 85 */
{"link", lx_link, 0, 2}, /* 86 */
{"unlink", NULL, 0, 1}, /* 87 */
{"symlink", NULL, 0, 2}, /* 88 */
{"readlink", NULL, 0, 3}, /* 89 */
{"unlink", lx_unlink, 0, 1}, /* 87 */
{"symlink", lx_symlink, 0, 2}, /* 88 */
{"readlink", lx_readlink, 0, 3}, /* 89 */
{"chmod", lx_chmod, 0, 2}, /* 90 */
{"fchmod", lx_fchmod, 0, 2}, /* 91 */
{"chown", lx_chown, 0, 3}, /* 92 */
Expand Down Expand Up @@ -1155,11 +1155,11 @@ lx_sysent_t lx_sysent64[] = {
{"fchownat", lx_fchownat, 0, 5}, /* 260 */
{"futimesat", NULL, 0, 3}, /* 261 */
{"fstatat64", lx_fstatat64, 0, 4}, /* 262 */
{"unlinkat", NULL, 0, 3}, /* 263 */
{"unlinkat", lx_unlinkat, 0, 3}, /* 263 */
{"renameat", NULL, 0, 4}, /* 264 */
{"linkat", lx_linkat, 0, 5}, /* 265 */
{"symlinkat", NULL, 0, 3}, /* 266 */
{"readlinkat", NULL, 0, 4}, /* 267 */
{"symlinkat", lx_symlinkat, 0, 3}, /* 266 */
{"readlinkat", lx_readlinkat, 0, 4}, /* 267 */
{"fchmodat", lx_fchmodat, 0, 3}, /* 268 */
{"faccessat", lx_faccessat, 0, 4}, /* 269 */
{"pselect6", lx_pselect, 0, 6}, /* 270 */
Expand Down
4 changes: 3 additions & 1 deletion usr/src/uts/common/brand/lx/sys/lx_misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
*/

/*
* Copyright 2015 Joyent, Inc. All rights reserved.
* Copyright 2016 Joyent, Inc.
*/

#ifndef _SYS__LX_MISC_H
Expand Down Expand Up @@ -48,6 +48,8 @@ extern void lx_exit_with_sig(proc_t *, sigqueue_t *);
extern boolean_t lx_wait_filter(proc_t *, proc_t *);
extern void lx_sigfd_translate(k_siginfo_t *);
extern int stol_ksiginfo_copyout(k_siginfo_t *, void *);

extern int ltos_at_flag(int, int, boolean_t);
#if defined(_SYSCALL32_IMPL)
extern int stol_ksiginfo32_copyout(k_siginfo_t *, void *);
#endif
Expand Down

0 comments on commit abec4d3

Please sign in to comment.