summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua M. Clulow <jmc@joyent.com>2015-02-25 16:43:20 -0800
committerJoshua M. Clulow <jmc@joyent.com>2015-02-26 00:43:20 +0000
commit890385b39da8bb050f8fa40ed15adb891808f66c (patch)
treeb59dc8638376572cba151a970d875b871d31f26e
parent4d8fab53f98471367ec2f1aaa7078b0e67104522 (diff)
downloadillumos-joyent-890385b39da8bb050f8fa40ed15adb891808f66c.tar.gz
OS-3923 lxbrand in-kernel chmod(2), fchmod(2) and fchmodat(2)
OS-3920 lxbrand use native *at(2) system calls for LX emulation Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
-rw-r--r--usr/src/lib/brand/lx/lx_brand/common/file.c43
-rw-r--r--usr/src/lib/brand/lx/lx_brand/common/lx_brand.c15
-rw-r--r--usr/src/lib/brand/lx/lx_brand/common/misc.c9
-rw-r--r--usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h3
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_brand.c8
-rw-r--r--usr/src/uts/common/brand/lx/os/lx_syscall.c12
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_brand.h9
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_fcntl.h (renamed from usr/src/lib/brand/lx/lx_brand/sys/lx_fcntl.h)37
-rw-r--r--usr/src/uts/common/brand/lx/sys/lx_syscalls.h15
-rw-r--r--usr/src/uts/common/brand/lx/syscall/lx_chmod.c70
-rw-r--r--usr/src/uts/intel/Makefile.files1
11 files changed, 143 insertions, 79 deletions
diff --git a/usr/src/lib/brand/lx/lx_brand/common/file.c b/usr/src/lib/brand/lx/lx_brand/common/file.c
index 1f2c4032f5..a3fc081c53 100644
--- a/usr/src/lib/brand/lx/lx_brand/common/file.c
+++ b/usr/src/lib/brand/lx/lx_brand/common/file.c
@@ -316,29 +316,6 @@ lx_fchown(uintptr_t p1, uintptr_t p2, uintptr_t p3)
}
long
-lx_chmod(uintptr_t p1, uintptr_t p2)
-{
- int ret;
-
- ret = chmod((const char *)p1, (mode_t)p2);
-
- if (ret < 0) {
- /*
- * If chown() failed and we're in install mode, return success
- * if the the reason we failed was because the source file
- * didn't actually exist or if we're trying to modify /dev/pts.
- */
- if ((lx_install != 0) &&
- ((errno == ENOENT) || (install_checkpath(p1) == 0)))
- return (0);
-
- return (-errno);
- }
-
- return (0);
-}
-
-long
lx_utime(uintptr_t p1, uintptr_t p2)
{
int ret;
@@ -868,23 +845,3 @@ lx_fchownat(uintptr_t ext1, uintptr_t p1, uintptr_t p2, uintptr_t p3,
else
return (lx_chown((uintptr_t)pathbuf, p2, p3));
}
-
-/*ARGSUSED*/
-long
-lx_fchmodat(uintptr_t ext1, uintptr_t p1, uintptr_t p2, uintptr_t p3)
-{
- int atfd = (int)ext1;
- char pathbuf[MAXPATHLEN];
- int ret;
-
- /*
- * It seems that at least some versions of glibc do not set or clear
- * the flags arg, so checking them will result in random behaviour.
- */
-
- ret = getpathat(atfd, p1, pathbuf, sizeof (pathbuf));
- if (ret < 0)
- return (ret);
-
- return (lx_chmod((uintptr_t)pathbuf, p2));
-}
diff --git a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
index 5c5dd53fff..3b88397860 100644
--- a/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
+++ b/usr/src/lib/brand/lx/lx_brand/common/lx_brand.c
@@ -583,6 +583,8 @@ lx_init(int argc, char *argv[], char *envp[])
void *vdso_hdr;
#endif
+ bzero(&reg, sizeof (reg));
+
stack_bottom = 2 * sysconf(_SC_PAGESIZE);
/*
@@ -621,6 +623,7 @@ lx_init(int argc, char *argv[], char *envp[])
* Are we in install mode?
*/
if (getenv("LX_INSTALL") != NULL) {
+ reg.lxbr_flags |= LX_PROC_INSTALL_MODE;
lx_install = 1;
lx_debug("INSTALL mode enabled.\n");
}
@@ -1049,8 +1052,8 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_unlink, /* 87: unlink */
lx_symlink, /* 88: symlink */
lx_readlink, /* 89: readlink */
- lx_chmod, /* 90: chmod */
- lx_fchmod, /* 91: fchmod */
+ NULL, /* 90: chmod */
+ NULL, /* 91: fchmod */
lx_chown, /* 92: chown */
lx_fchown, /* 93: fchown */
lx_lchown, /* 94: lchown */
@@ -1227,7 +1230,7 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_linkat, /* 265: linkat */
lx_symlinkat, /* 266: symlinkat */
lx_readlinkat, /* 267: readlinkat */
- lx_fchmodat, /* 268: fchmodat */
+ NULL, /* 268: fchmodat */
lx_faccessat, /* 269: faccessat */
lx_pselect6, /* 270: pselect6 */
lx_ppoll, /* 271: ppoll */
@@ -1305,7 +1308,7 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_chdir, /* 12: chdir */
lx_time, /* 13: time */
lx_mknod, /* 14: mknod */
- lx_chmod, /* 15: chmod */
+ NULL, /* 15: chmod */
lx_lchown16, /* 16: lchown16 */
NULL, /* 17: break */
NULL, /* 18: stat */
@@ -1384,7 +1387,7 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_munmap, /* 91: munmap */
lx_truncate, /* 92: truncate */
lx_ftruncate, /* 93: ftruncate */
- lx_fchmod, /* 94: fchmod */
+ NULL, /* 94: fchmod */
lx_fchown16, /* 95: fchown16 */
lx_getpriority, /* 96: getpriority */
lx_setpriority, /* 97: setpriority */
@@ -1596,7 +1599,7 @@ static lx_syscall_handler_t lx_handlers[] = {
lx_linkat, /* 303: linkat */
lx_symlinkat, /* 304: symlinkat */
lx_readlinkat, /* 305: readlinkat */
- lx_fchmodat, /* 306: fchmodat */
+ NULL, /* 306: fchmodat */
lx_faccessat, /* 307: faccessat */
lx_pselect6, /* 308: pselect6 */
lx_ppoll, /* 309: ppoll */
diff --git a/usr/src/lib/brand/lx/lx_brand/common/misc.c b/usr/src/lib/brand/lx/lx_brand/common/misc.c
index 7e16fb717e..e3bb34dadc 100644
--- a/usr/src/lib/brand/lx/lx_brand/common/misc.c
+++ b/usr/src/lib/brand/lx/lx_brand/common/misc.c
@@ -823,15 +823,6 @@ lx_fchdir(int fildes)
return ((r == -1) ? -errno : r);
}
-long
-lx_fchmod(int fildes, mode_t mode)
-{
- int r;
-
- r = fchmod(fildes, mode);
- return ((r == -1) ? -errno : r);
-}
-
/*
* We support neither the second argument (NUMA node), nor the third (obsolete
* pre-2.6.24 caching functionality which was ultimately broken).
diff --git a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h
index 4cc72ba0c6..7aed33752f 100644
--- a/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h
+++ b/usr/src/lib/brand/lx/lx_brand/sys/lx_syscall.h
@@ -56,7 +56,6 @@ extern long lx_renameat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
extern long lx_linkat(uintptr_t, 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_fchmodat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
extern long lx_access(uintptr_t, uintptr_t);
extern long lx_faccessat(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
@@ -184,7 +183,6 @@ extern long lx_fchown16(uintptr_t, uintptr_t, uintptr_t);
extern long lx_lchown16(uintptr_t, uintptr_t, uintptr_t);
extern long lx_chown(uintptr_t, uintptr_t, uintptr_t);
extern long lx_fchown(uintptr_t, uintptr_t, uintptr_t);
-extern long lx_chmod(uintptr_t, uintptr_t);
extern long lx_rename(uintptr_t, uintptr_t);
extern long lx_utime(uintptr_t, uintptr_t);
extern long lx_llseek(uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t);
@@ -319,7 +317,6 @@ extern long lx_epoll_wait(int, void *, int, int);
extern long lx_eventfd(unsigned int);
extern long lx_eventfd2(unsigned int, int);
extern long lx_fchdir(int);
-extern long lx_fchmod(int, mode_t);
extern long lx_getgid(void);
extern long lx_getgroups(int, gid_t *);
extern long lx_getitimer(int, struct itimerval *);
diff --git a/usr/src/uts/common/brand/lx/os/lx_brand.c b/usr/src/uts/common/brand/lx/os/lx_brand.c
index fc9aaa6055..a2f38da9dd 100644
--- a/usr/src/uts/common/brand/lx/os/lx_brand.c
+++ b/usr/src/uts/common/brand/lx/os/lx_brand.c
@@ -805,6 +805,7 @@ lx_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2,
reg.lxbr_version = (uint_t)reg32.lxbr_version;
reg.lxbr_handler =
(void *)(uintptr_t)reg32.lxbr_handler;
+ reg.lxbr_flags = reg32.lxbr_flags;
}
#endif
@@ -814,10 +815,17 @@ lx_brandsys(int cmd, int64_t *rval, uintptr_t arg1, uintptr_t arg2,
return (EINVAL);
}
+ if ((reg.lxbr_flags & ~LX_PROC_ALL) != 0) {
+ lx_print("Invalid brand flags (%u)\n",
+ reg.lxbr_flags);
+ return (EINVAL);
+ }
+
lx_print("Assigning brand 0x%p and handler 0x%p to proc 0x%p\n",
(void *)&lx_brand, (void *)reg.lxbr_handler, (void *)p);
pd = p->p_brand_data;
pd->l_handler = (uintptr_t)reg.lxbr_handler;
+ pd->l_flags = reg.lxbr_flags;
return (0);
diff --git a/usr/src/uts/common/brand/lx/os/lx_syscall.c b/usr/src/uts/common/brand/lx/os/lx_syscall.c
index 09a3e9bbba..eb4ce1e8f6 100644
--- a/usr/src/uts/common/brand/lx/os/lx_syscall.c
+++ b/usr/src/uts/common/brand/lx/os/lx_syscall.c
@@ -441,7 +441,7 @@ lx_sysent_t lx_sysent32[] = {
{"chdir", NULL, 0, 1}, /* 12 */
{"time", NULL, 0, 1}, /* 13 */
{"mknod", NULL, 0, 3}, /* 14 */
- {"chmod", NULL, 0, 2}, /* 15 */
+ {"chmod", lx_chmod, 0, 2}, /* 15 */
{"lchown16", NULL, 0, 3}, /* 16 */
{"break", NULL, NOSYS_OBSOLETE, 0}, /* 17 */
{"stat", NULL, NOSYS_OBSOLETE, 0}, /* 18 */
@@ -520,7 +520,7 @@ lx_sysent_t lx_sysent32[] = {
{"munmap", NULL, 0, 2}, /* 91 */
{"truncate", NULL, 0, 2}, /* 92 */
{"ftruncate", NULL, 0, 2}, /* 93 */
- {"fchmod", NULL, 0, 2}, /* 94 */
+ {"fchmod", lx_fchmod, 0, 2}, /* 94 */
{"fchown16", NULL, 0, 3}, /* 95 */
{"getpriority", NULL, 0, 2}, /* 96 */
{"setpriority", NULL, 0, 3}, /* 97 */
@@ -736,7 +736,7 @@ lx_sysent_t lx_sysent32[] = {
{"linkat", NULL, 0, 5}, /* 303 */
{"symlinkat", NULL, 0, 3}, /* 304 */
{"readlinkat", NULL, 0, 4}, /* 305 */
- {"fchmodat", NULL, 0, 4}, /* 306 */
+ {"fchmodat", lx_fchmodat, 0, 3}, /* 306 */
{"faccessat", NULL, 0, 4}, /* 307 */
{"pselect6", NULL, LX_SYS_EBPARG6, 6}, /* 308 */
{"ppoll", NULL, 0, 5}, /* 309 */
@@ -887,8 +887,8 @@ lx_sysent_t lx_sysent64[] = {
{"unlink", NULL, 0, 1}, /* 87 */
{"symlink", NULL, 0, 2}, /* 88 */
{"readlink", NULL, 0, 3}, /* 89 */
- {"chmod", NULL, 0, 2}, /* 90 */
- {"fchmod", NULL, 0, 2}, /* 91 */
+ {"chmod", lx_chmod, 0, 2}, /* 90 */
+ {"fchmod", lx_fchmod, 0, 2}, /* 91 */
{"chown", NULL, 0, 3}, /* 92 */
{"fchown", NULL, 0, 3}, /* 93 */
{"lchown", NULL, 0, 3}, /* 94 */
@@ -1065,7 +1065,7 @@ lx_sysent_t lx_sysent64[] = {
{"linkat", NULL, 0, 5}, /* 265 */
{"symlinkat", NULL, 0, 3}, /* 266 */
{"readlinkat", NULL, 0, 4}, /* 267 */
- {"fchmodat", NULL, 0, 4}, /* 268 */
+ {"fchmodat", lx_fchmodat, 0, 3}, /* 268 */
{"faccessat", NULL, 0, 4}, /* 269 */
{"pselect6", NULL, 0, 6}, /* 270 */
{"ppoll", NULL, 0, 5}, /* 271 */
diff --git a/usr/src/uts/common/brand/lx/sys/lx_brand.h b/usr/src/uts/common/brand/lx/sys/lx_brand.h
index 543373b5fa..f3c46dd7fd 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_brand.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_brand.h
@@ -203,11 +203,13 @@ extern struct brand lx_brand;
typedef struct lx_brand_registration {
uint_t lxbr_version; /* version number */
void *lxbr_handler; /* base address of handler */
+ uint32_t lxbr_flags; /* LX_PROC_* registration flags */
} lx_brand_registration_t;
typedef struct lx_brand_registration32 {
uint_t lxbr_version; /* version number */
uint32_t lxbr_handler; /* base address of handler */
+ uint32_t lxbr_flags; /* LX_PROC_* registration flags */
} lx_brand_registration32_t;
#ifdef __amd64
@@ -392,6 +394,12 @@ typedef lx_elf_data64_t lx_elf_data_t;
typedef lx_elf_data32_t lx_elf_data_t;
#endif
+typedef enum lx_proc_flags {
+ LX_PROC_INSTALL_MODE = 0x01
+} lx_proc_flags_t;
+
+#define LX_PROC_ALL LX_PROC_INSTALL_MODE
+
#ifdef _KERNEL
typedef struct lx_proc_data {
@@ -401,6 +409,7 @@ typedef struct lx_proc_data {
lx_elf_data_t l_elf_data; /* ELF data for linux executable */
int l_signal; /* signal to deliver to parent when this */
/* thread group dies */
+ lx_proc_flags_t l_flags;
} lx_proc_data_t;
#endif /* _KERNEL */
diff --git a/usr/src/lib/brand/lx/lx_brand/sys/lx_fcntl.h b/usr/src/uts/common/brand/lx/sys/lx_fcntl.h
index 06e05cbf5c..f3b472e7ff 100644
--- a/usr/src/lib/brand/lx/lx_brand/sys/lx_fcntl.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_fcntl.h
@@ -21,7 +21,7 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
- * Copyright 2014 Joyent, Inc. All rights reserved.
+ * Copyright 2015 Joyent, Inc.
*/
#ifndef _SYS_LX_FCNTL_H
@@ -94,7 +94,7 @@ extern "C" {
* AT_REMOVEDIR is used only by unlinkat and AT_EACCESS is used only by
* faccessat.
*/
-#define LX_AT_FDCWD -100
+#define LX_AT_FDCWD (-100)
#define LX_AT_SYMLINK_NOFOLLOW 0x100
#define LX_AT_REMOVEDIR 0x200
#define LX_AT_EACCESS 0x200
@@ -102,21 +102,46 @@ extern "C" {
#define LX_AT_NO_AUTOMOUNT 0x800
#define LX_AT_EMPTY_PATH 0x1000
-struct lx_flock {
+typedef struct lx_flock {
short l_type;
short l_whence;
long l_start;
long l_len;
int l_pid;
-};
+} lx_flock_t;
-struct lx_flock64 {
+typedef struct lx_flock64 {
short l_type;
short l_whence;
long long l_start;
long long l_len;
int l_pid;
-};
+} lx_flock64_t;
+
+#if defined(_KERNEL) && defined(_SYSCALL32_IMPL)
+
+/*
+ * 64-bit kernel view of 32-bit usermode structs.
+ */
+#pragma pack(4)
+typedef struct lx_flock32 {
+ int16_t l_type;
+ int16_t l_whence;
+ int32_t l_start;
+ int32_t l_len;
+ int32_t l_pid;
+} lx_flock32_t;
+
+typedef struct lx_flock64_32 {
+ int16_t l_type;
+ int16_t l_whence;
+ int64_t l_start;
+ int64_t l_len;
+ int32_t l_pid;
+} lx_flock64_32_t;
+#pragma pack()
+
+#endif /* _KERNEL && _SYSCALL32_IMPL */
#ifdef __cplusplus
}
diff --git a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
index 2d9abf2fe6..6943b40310 100644
--- a/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
+++ b/usr/src/uts/common/brand/lx/sys/lx_syscalls.h
@@ -36,19 +36,20 @@ extern "C" {
extern long lx_arch_prctl();
extern long lx_brk();
+extern long lx_chmod();
+extern long lx_fchmod();
+extern long lx_fchmodat();
+extern long lx_futex();
+extern long lx_get_thread_area();
extern long lx_getpid();
extern long lx_getppid();
+extern long lx_gettid();
+extern long lx_ioctl();
extern long lx_kill();
-extern long lx_tkill();
-extern long lx_tgkill();
extern long lx_modify_ldt();
extern long lx_pipe();
extern long lx_pipe2();
extern long lx_read();
-extern long lx_ioctl();
-extern long lx_gettid();
-extern long lx_futex();
-extern long lx_get_thread_area();
extern long lx_sched_getparam();
extern long lx_sched_getscheduler();
extern long lx_sched_rr_get_interval();
@@ -63,6 +64,8 @@ extern long lx_setresuid();
extern long lx_setresuid16();
extern long lx_sysinfo32();
extern long lx_sysinfo64();
+extern long lx_tgkill();
+extern long lx_tkill();
extern long lx_wait4();
extern long lx_waitid();
extern long lx_waitpid();
diff --git a/usr/src/uts/common/brand/lx/syscall/lx_chmod.c b/usr/src/uts/common/brand/lx/syscall/lx_chmod.c
new file mode 100644
index 0000000000..66a4e35a63
--- /dev/null
+++ b/usr/src/uts/common/brand/lx/syscall/lx_chmod.c
@@ -0,0 +1,70 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2015 Joyent, Inc.
+ */
+
+#include <sys/fcntl.h>
+#include <sys/thread.h>
+#include <sys/klwp.h>
+#include <sys/lx_brand.h>
+#include <sys/lx_fcntl.h>
+
+/*
+ * From "uts/common/syscall/chmod.c":
+ */
+extern int fchmodat(int, char *, int, int);
+
+static long
+lx_fchmodat_wrapper(int fd, char *path, int mode, int flag)
+{
+ long rval;
+
+ if (fd == LX_AT_FDCWD) {
+ fd = AT_FDCWD;
+ }
+
+ if ((rval = fchmodat(fd, path, mode, flag)) != 0) {
+ lx_proc_data_t *pd = ttolxproc(curthread);
+ klwp_t *lwp = ttolwp(curthread);
+
+ /*
+ * If the process is in "install mode", return success
+ * if the operation failed due to an absent file.
+ */
+ if ((pd->l_flags & LX_PROC_INSTALL_MODE) &&
+ lwp->lwp_errno == ENOENT) {
+ lwp->lwp_errno = 0;
+ return (0);
+ }
+ }
+
+ return (rval);
+}
+
+long
+lx_fchmodat(int fd, char *path, int mode)
+{
+ return (lx_fchmodat_wrapper(fd, path, mode, 0));
+}
+
+long
+lx_fchmod(int fd, int mode)
+{
+ return (lx_fchmodat_wrapper(fd, NULL, mode, 0));
+}
+
+long
+lx_chmod(char *path, int mode)
+{
+ return (lx_fchmodat_wrapper(AT_FDCWD, path, mode, 0));
+}
diff --git a/usr/src/uts/intel/Makefile.files b/usr/src/uts/intel/Makefile.files
index 7eefb1c062..0b99fc7e9c 100644
--- a/usr/src/uts/intel/Makefile.files
+++ b/usr/src/uts/intel/Makefile.files
@@ -279,6 +279,7 @@ LX_BRAND_OBJS = \
lx_archdep.o \
lx_brand.o \
lx_brk.o \
+ lx_chmod.o \
lx_clone.o \
lx_futex.o \
lx_getpid.o \