summaryrefslogtreecommitdiff
path: root/usr/src/uts/common
diff options
context:
space:
mode:
authorRoger A. Faulkner <Roger.Faulkner@Oracle.COM>2010-07-07 17:36:17 -0700
committerRoger A. Faulkner <Roger.Faulkner@Oracle.COM>2010-07-07 17:36:17 -0700
commit794f0adb050e571bbfde4d2a19b9f88b852079dd (patch)
treec1735b3eda175e9096f5b062a73614e73aa5cd9a /usr/src/uts/common
parent07925104db56e5c3eacc4865b918bd16af5cec59 (diff)
downloadillumos-joyent-794f0adb050e571bbfde4d2a19b9f88b852079dd.tar.gz
PSARC 2010/235 POSIX 1003.1-2008 *at(2) syscalls
6910251 need support for all POSIX.1-2008 *at(2) syscalls 6964835 mknod(2) auditing omits the pathname for invalid arguments
Diffstat (limited to 'usr/src/uts/common')
-rw-r--r--usr/src/uts/common/brand/sn1/sn1_brand.c2
-rw-r--r--usr/src/uts/common/brand/solaris10/s10_brand.c7
-rw-r--r--usr/src/uts/common/brand/solaris10/s10_brand.h8
-rw-r--r--usr/src/uts/common/c2/audit.c7
-rw-r--r--usr/src/uts/common/c2/audit_event.c196
-rw-r--r--usr/src/uts/common/c2/audit_kevents.h4
-rw-r--r--usr/src/uts/common/fs/lookup.c13
-rw-r--r--usr/src/uts/common/fs/vnode.c35
-rw-r--r--usr/src/uts/common/os/core.c6
-rw-r--r--usr/src/uts/common/os/exit.c4
-rw-r--r--usr/src/uts/common/os/fio.c150
-rw-r--r--usr/src/uts/common/os/sysent.c32
-rw-r--r--usr/src/uts/common/sys/acct.h21
-rw-r--r--usr/src/uts/common/sys/fcntl.h15
-rw-r--r--usr/src/uts/common/sys/file.h23
-rw-r--r--usr/src/uts/common/sys/pathname.h16
-rw-r--r--usr/src/uts/common/sys/stat.h15
-rw-r--r--usr/src/uts/common/sys/syscall.h9
-rw-r--r--usr/src/uts/common/sys/vnode.h5
-rw-r--r--usr/src/uts/common/syscall/access.c51
-rw-r--r--usr/src/uts/common/syscall/chmod.c54
-rw-r--r--usr/src/uts/common/syscall/chown.c82
-rw-r--r--usr/src/uts/common/syscall/fcntl.c16
-rw-r--r--usr/src/uts/common/syscall/getdents.c12
-rw-r--r--usr/src/uts/common/syscall/link.c47
-rw-r--r--usr/src/uts/common/syscall/mkdir.c32
-rw-r--r--usr/src/uts/common/syscall/mknod.c30
-rw-r--r--usr/src/uts/common/syscall/open.c25
-rw-r--r--usr/src/uts/common/syscall/readlink.c52
-rw-r--r--usr/src/uts/common/syscall/rename.c69
-rw-r--r--usr/src/uts/common/syscall/stat.c2
-rw-r--r--usr/src/uts/common/syscall/symlink.c43
-rw-r--r--usr/src/uts/common/syscall/unlink.c43
-rw-r--r--usr/src/uts/common/syscall/utime.c5
34 files changed, 681 insertions, 450 deletions
diff --git a/usr/src/uts/common/brand/sn1/sn1_brand.c b/usr/src/uts/common/brand/sn1/sn1_brand.c
index 3d5fc7111a..d61928d578 100644
--- a/usr/src/uts/common/brand/sn1/sn1_brand.c
+++ b/usr/src/uts/common/brand/sn1/sn1_brand.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -248,7 +249,6 @@ _init(void)
sn1_emulation_table[SYS_times] = 1; /* 43 */
sn1_emulation_table[SYS_getgid] = 1; /* 47 */
sn1_emulation_table[SYS_utssys] = 1; /* 57 */
- sn1_emulation_table[SYS_readlink] = 1; /* 90 */
sn1_emulation_table[SYS_waitid] = 1; /* 107 */
sn1_emulation_table[SYS_uname] = 1; /* 135 */
diff --git a/usr/src/uts/common/brand/solaris10/s10_brand.c b/usr/src/uts/common/brand/solaris10/s10_brand.c
index 2adf25b453..0cad868679 100644
--- a/usr/src/uts/common/brand/solaris10/s10_brand.c
+++ b/usr/src/uts/common/brand/solaris10/s10_brand.c
@@ -511,8 +511,11 @@ _init(void)
s10_emulation_table[S10_SYS_open] = 1; /* 5 */
s10_emulation_table[S10_SYS_wait] = 1; /* 7 */
s10_emulation_table[S10_SYS_creat] = 1; /* 8 */
+ s10_emulation_table[S10_SYS_link] = 1; /* 9 */
s10_emulation_table[S10_SYS_unlink] = 1; /* 10 */
s10_emulation_table[S10_SYS_exec] = 1; /* 11 */
+ s10_emulation_table[S10_SYS_mknod] = 1; /* 14 */
+ s10_emulation_table[S10_SYS_chmod] = 1; /* 15 */
s10_emulation_table[S10_SYS_chown] = 1; /* 16 */
s10_emulation_table[S10_SYS_stat] = 1; /* 18 */
s10_emulation_table[S10_SYS_umount] = 1; /* 22 */
@@ -527,9 +530,13 @@ _init(void)
s10_emulation_table[S10_SYS_issetugid] = 1; /* 75 */
s10_emulation_table[S10_SYS_fsat] = 1; /* 76 */
s10_emulation_table[S10_SYS_rmdir] = 1; /* 79 */
+ s10_emulation_table[S10_SYS_mkdir] = 1; /* 80 */
s10_emulation_table[SYS_getdents] = 1; /* 81 */
s10_emulation_table[S10_SYS_poll] = 1; /* 87 */
s10_emulation_table[S10_SYS_lstat] = 1; /* 88 */
+ s10_emulation_table[S10_SYS_symlink] = 1; /* 89 */
+ s10_emulation_table[S10_SYS_readlink] = 1; /* 90 */
+ s10_emulation_table[S10_SYS_fchmod] = 1; /* 93 */
s10_emulation_table[S10_SYS_fchown] = 1; /* 94 */
s10_emulation_table[SYS_sigprocmask] = 1; /* 95 */
s10_emulation_table[SYS_sigsuspend] = 1; /* 96 */
diff --git a/usr/src/uts/common/brand/solaris10/s10_brand.h b/usr/src/uts/common/brand/solaris10/s10_brand.h
index 3686c3600e..0112a783bb 100644
--- a/usr/src/uts/common/brand/solaris10/s10_brand.h
+++ b/usr/src/uts/common/brand/solaris10/s10_brand.h
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -106,8 +107,11 @@ enum s10_emulated_features {
#define S10_SYS_open 5
#define S10_SYS_wait 7
#define S10_SYS_creat 8
+#define S10_SYS_link 9
#define S10_SYS_unlink 10
#define S10_SYS_exec 11
+#define S10_SYS_mknod 14
+#define S10_SYS_chmod 15
#define S10_SYS_chown 16
#define S10_SYS_stat 18
#define S10_SYS_umount 22
@@ -118,8 +122,12 @@ enum s10_emulated_features {
#define S10_SYS_issetugid 75
#define S10_SYS_fsat 76
#define S10_SYS_rmdir 79
+#define S10_SYS_mkdir 80
#define S10_SYS_poll 87
#define S10_SYS_lstat 88
+#define S10_SYS_symlink 89
+#define S10_SYS_readlink 90
+#define S10_SYS_fchmod 93
#define S10_SYS_fchown 94
#define S10_SYS_xstat 123
#define S10_SYS_lxstat 124
diff --git a/usr/src/uts/common/c2/audit.c b/usr/src/uts/common/c2/audit.c
index aa3fd4e1b9..bbaf783668 100644
--- a/usr/src/uts/common/c2/audit.c
+++ b/usr/src/uts/common/c2/audit.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -1026,20 +1027,26 @@ audit_setfsat_path(int argnum)
switch (tad->tad_scid) {
case SYS_faccessat:
+ case SYS_fchmodat:
case SYS_fchownat:
case SYS_fstatat:
case SYS_fstatat64:
+ case SYS_mkdirat:
+ case SYS_mknodat:
case SYS_openat:
case SYS_openat64:
+ case SYS_readlinkat:
case SYS_unlinkat:
fd = uap->arg1;
break;
+ case SYS_linkat:
case SYS_renameat:
if (argnum == 3)
fd = uap->arg3;
else
fd = uap->arg1;
break;
+ case SYS_symlinkat:
case SYS_utimesys:
fd = uap->arg2;
break;
diff --git a/usr/src/uts/common/c2/audit_event.c b/usr/src/uts/common/c2/audit_event.c
index 270fa59c96..69464b2b32 100644
--- a/usr/src/uts/common/c2/audit_event.c
+++ b/usr/src/uts/common/c2/audit_event.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 1992, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -80,6 +81,7 @@
char _depends_on[] = "fs/sockfs";
static au_event_t aui_fchownat(au_event_t);
+static au_event_t aui_fchmodat(au_event_t);
static au_event_t aui_open(au_event_t);
static au_event_t aui_openat(au_event_t);
static au_event_t aui_unlinkat(au_event_t);
@@ -114,9 +116,12 @@ static void aus_fchownat(struct t_audit_data *);
static void aus_chmod(struct t_audit_data *);
static void aus_facl(struct t_audit_data *);
static void aus_fchmod(struct t_audit_data *);
+static void aus_fchmodat(struct t_audit_data *);
static void aus_fcntl(struct t_audit_data *);
static void aus_mkdir(struct t_audit_data *);
+static void aus_mkdirat(struct t_audit_data *);
static void aus_mknod(struct t_audit_data *);
+static void aus_mknodat(struct t_audit_data *);
static void aus_mount(struct t_audit_data *);
static void aus_umount2(struct t_audit_data *);
static void aus_msgsys(struct t_audit_data *);
@@ -149,6 +154,7 @@ static void aus_setreuid(struct t_audit_data *);
static void aus_labelsys(struct t_audit_data *);
static void auf_mknod(struct t_audit_data *, int, rval_t *);
+static void auf_mknodat(struct t_audit_data *, int, rval_t *);
static void auf_msgsys(struct t_audit_data *, int, rval_t *);
static void auf_semsys(struct t_audit_data *, int, rval_t *);
static void auf_shmsys(struct t_audit_data *, int, rval_t *);
@@ -210,7 +216,7 @@ aui_open, AUE_OPEN, aus_open, /* 5 open */
auf_null, S2E_SP,
aui_null, AUE_CLOSE, aus_close, /* 6 close */
auf_null, 0,
-aui_null, AUE_NULL, aus_null, /* 7 (loadable) was wait */
+aui_null, AUE_LINK, aus_null, /* 7 linkat */
auf_null, 0,
aui_null, AUE_NULL, aus_null, /* 8 (loadable) was creat */
auf_null, 0,
@@ -218,14 +224,14 @@ aui_null, AUE_LINK, aus_null, /* 9 link */
auf_null, 0,
aui_null, AUE_UNLINK, aus_null, /* 10 unlink */
auf_null, 0,
-aui_null, AUE_NULL, aus_null, /* 11 (loadable) was exec */
+aui_null, AUE_SYMLINK, aus_null, /* 11 symlinkat */
auf_null, 0,
aui_null, AUE_CHDIR, aus_null, /* 12 chdir */
auf_null, S2E_SP,
aui_null, AUE_NULL, aus_null, /* 13 time */
auf_null, 0,
aui_null, AUE_MKNOD, aus_mknod, /* 14 mknod */
- auf_mknod, 0,
+ auf_mknod, S2E_MLD,
aui_null, AUE_CHMOD, aus_chmod, /* 15 chmod */
auf_null, 0,
aui_null, AUE_CHOWN, aus_chown, /* 16 chown */
@@ -240,8 +246,8 @@ aui_null, AUE_NULL, aus_null, /* 20 getpid */
auf_null, 0,
aui_null, AUE_MOUNT, aus_mount, /* 21 mount */
auf_null, S2E_MLD,
-aui_null, AUE_NULL, aus_null, /* 22 (loadable) was umount */
- auf_null, 0,
+aui_null, AUE_READLINK, aus_null, /* 22 readlinkat */
+ auf_null, S2E_PUB,
aui_null, AUE_SETUID, aus_setuid, /* 23 setuid */
auf_null, 0,
aui_null, AUE_NULL, aus_null, /* 24 getuid */
@@ -292,8 +298,8 @@ aui_null, AUE_SETGID, aus_setgid, /* 46 setgid */
auf_null, 0,
aui_null, AUE_NULL, aus_null, /* 47 getgid */
auf_null, 0,
-aui_null, AUE_NULL, aus_null, /* 48 (loadable) was ssig */
- auf_null, 0,
+aui_null, AUE_MKNOD, aus_mknodat, /* 48 mknodat */
+ auf_mknodat, S2E_MLD,
aui_msgsys, AUE_MSGSYS, aus_msgsys, /* 49 (loadable) msgsys */
auf_msgsys, 0,
#if defined(__x86)
@@ -403,9 +409,9 @@ aui_null, AUE_NULL, aus_null, /* 99 sigpending */
auf_null, 0,
aui_null, AUE_NULL, aus_null, /* 100 setcontext */
auf_null, 0,
-aui_null, AUE_NULL, aus_null, /* 101 (loadable) */
+aui_fchmodat, AUE_NULL, aus_fchmodat, /* 101 fchmodat */
auf_null, 0,
-aui_null, AUE_NULL, aus_null, /* 102 (loadable) */
+aui_null, AUE_MKDIR, aus_mkdirat, /* 102 mkdirat */
auf_null, 0,
aui_null, AUE_STATVFS, aus_null, /* 103 statvfs */
auf_null, S2E_PUB,
@@ -890,7 +896,6 @@ aus_fchownat(struct t_audit_data *tad)
au_uwrite(au_to_arg32(4, "new file gid", gid));
}
-/* chmod start function */
/*ARGSUSED*/
static void
aus_chmod(struct t_audit_data *tad)
@@ -908,7 +913,6 @@ aus_chmod(struct t_audit_data *tad)
au_uwrite(au_to_arg32(2, "new file mode", fmode&07777));
}
-/* chmod start function */
/*ARGSUSED*/
static void
aus_fchmod(struct t_audit_data *tad)
@@ -929,14 +933,82 @@ aus_fchmod(struct t_audit_data *tad)
au_uwrite(au_to_arg32(2, "new file mode", fmode&07777));
- /*
- * convert file pointer to file descriptor
- * Note: fd ref count incremented here.
- */
+ /*
+ * convert file pointer to file descriptor
+ * Note: fd ref count incremented here.
+ */
if ((fp = getf(fd)) == NULL)
return;
- /* get path from file struct here */
+ /* get path from file struct here */
+ fad = F2A(fp);
+ if (fad->fad_aupath != NULL) {
+ au_uwrite(au_to_path(fad->fad_aupath));
+ } else {
+ au_uwrite(au_to_arg32(1, "no path: fd", fd));
+ }
+
+ vp = fp->f_vnode;
+ audit_attributes(vp);
+
+ /* decrement file descriptor reference count */
+ releasef(fd);
+}
+
+static au_event_t
+aui_fchmodat(au_event_t e)
+{
+ klwp_t *clwp = ttolwp(curthread);
+
+ struct a {
+ long fd;
+ long fname; /* char * */
+ long fmode;
+ long flag;
+ } *uap = (struct a *)clwp->lwp_ap;
+
+ if (uap->fname == NULL)
+ e = AUE_FCHMOD;
+ else
+ e = AUE_CHMOD;
+
+ return (e);
+}
+
+/*ARGSUSED*/
+static void
+aus_fchmodat(struct t_audit_data *tad)
+{
+ klwp_t *clwp = ttolwp(curthread);
+ uint32_t fmode;
+ uint32_t fd;
+ struct file *fp;
+ struct vnode *vp;
+ struct f_audit_data *fad;
+
+ struct a {
+ long fd;
+ long fname; /* char * */
+ long fmode;
+ long flag;
+ } *uap = (struct a *)clwp->lwp_ap;
+
+ fd = (uint32_t)uap->fd;
+ fmode = (uint32_t)uap->fmode;
+
+ au_uwrite(au_to_arg32(2, "new file mode", fmode&07777));
+
+ if (fd == AT_FDCWD || uap->fname != NULL) /* same as chmod() */
+ return;
+
+ /*
+ * convert file pointer to file descriptor
+ * Note: fd ref count incremented here.
+ */
+ if ((fp = getf(fd)) == NULL)
+ return;
+
+ /* get path from file struct here */
fad = F2A(fp);
if (fad->fad_aupath != NULL) {
au_uwrite(au_to_path(fad->fad_aupath));
@@ -959,7 +1031,7 @@ open_event(uint_t fm)
{
au_event_t e;
- switch (fm & (O_RDONLY|O_WRONLY|O_RDWR|O_CREAT|O_TRUNC)) {
+ switch (fm & (O_ACCMODE | O_CREAT | O_TRUNC)) {
case O_RDONLY:
e = AUE_OPEN_R;
break;
@@ -996,6 +1068,12 @@ open_event(uint_t fm)
case O_RDWR | O_TRUNC | O_CREAT:
e = AUE_OPEN_RWTC;
break;
+ case O_SEARCH:
+ e = AUE_OPEN_S;
+ break;
+ case O_EXEC:
+ e = AUE_OPEN_E;
+ break;
default:
e = AUE_NULL;
break;
@@ -1502,6 +1580,24 @@ aus_mkdir(struct t_audit_data *tad)
/*ARGSUSED*/
static void
+aus_mkdirat(struct t_audit_data *tad)
+{
+ klwp_t *clwp = ttolwp(curthread);
+ uint32_t dmode;
+
+ struct a {
+ long fd;
+ long dirnamep; /* char * */
+ long dmode;
+ } *uap = (struct a *)clwp->lwp_ap;
+
+ dmode = (uint32_t)uap->dmode;
+
+ au_uwrite(au_to_arg32(2, "mode", dmode));
+}
+
+/*ARGSUSED*/
+static void
aus_mknod(struct t_audit_data *tad)
{
klwp_t *clwp = ttolwp(curthread);
@@ -1540,19 +1636,77 @@ auf_mknod(struct t_audit_data *tad, int error, rval_t *rval)
} *uap = (struct a *)clwp->lwp_ap;
/* no error, then already path token in audit record */
- if (error != EPERM)
+ if (error != EPERM && error != EINVAL)
return;
- /* not auditing this event, nothing then to do */
- if (tad->tad_flag == 0)
+ /* do the lookup to force generation of path token */
+ pnamep = (caddr_t)uap->pnamep;
+ tad->tad_ctrl |= TAD_NOATTRB;
+ error = lookupname(pnamep, UIO_USERSPACE, NO_FOLLOW, &dvp, NULLVPP);
+ if (error == 0)
+ VN_RELE(dvp);
+}
+
+/*ARGSUSED*/
+static void
+aus_mknodat(struct t_audit_data *tad)
+{
+ klwp_t *clwp = ttolwp(curthread);
+ uint32_t fmode;
+ dev_t dev;
+
+ struct a {
+ long fd;
+ long pnamep; /* char * */
+ long fmode;
+ long dev;
+ } *uap = (struct a *)clwp->lwp_ap;
+
+ fmode = (uint32_t)uap->fmode;
+ dev = (dev_t)uap->dev;
+
+ au_uwrite(au_to_arg32(2, "mode", fmode));
+#ifdef _LP64
+ au_uwrite(au_to_arg64(3, "dev", dev));
+#else
+ au_uwrite(au_to_arg32(3, "dev", dev));
+#endif
+}
+
+/*ARGSUSED*/
+static void
+auf_mknodat(struct t_audit_data *tad, int error, rval_t *rval)
+{
+ klwp_t *clwp = ttolwp(curthread);
+ vnode_t *startvp;
+ vnode_t *dvp;
+ caddr_t pnamep;
+ int fd;
+
+ struct a {
+ long fd;
+ long pnamep; /* char * */
+ long fmode;
+ long dev;
+ } *uap = (struct a *)clwp->lwp_ap;
+
+ /* no error, then already path token in audit record */
+ if (error != EPERM && error != EINVAL)
return;
/* do the lookup to force generation of path token */
+ fd = (int)uap->fd;
pnamep = (caddr_t)uap->pnamep;
+ if (pnamep == NULL ||
+ fgetstartvp(fd, pnamep, &startvp) != 0)
+ return;
tad->tad_ctrl |= TAD_NOATTRB;
- error = lookupname(pnamep, UIO_USERSPACE, NO_FOLLOW, &dvp, NULLVPP);
+ error = lookupnameat(pnamep, UIO_USERSPACE, NO_FOLLOW, &dvp, NULLVPP,
+ startvp);
if (error == 0)
VN_RELE(dvp);
+ if (startvp != NULL)
+ VN_RELE(startvp);
}
/*ARGSUSED*/
diff --git a/usr/src/uts/common/c2/audit_kevents.h b/usr/src/uts/common/c2/audit_kevents.h
index b106fdd3d6..758654dfcc 100644
--- a/usr/src/uts/common/c2/audit_kevents.h
+++ b/usr/src/uts/common/c2/audit_kevents.h
@@ -159,8 +159,10 @@ extern "C" {
#define AUE_ASYNC_DAEMON_EXIT 114 /* =no async_daemon(2) exited */
#define AUE_NFSSVC_EXIT 115 /* =no nfssvc(2) exited */
#define AUE_PFEXEC 116 /* =ps,ex,ua,as execve(2) w/ pfexec */
+#define AUE_OPEN_S 117 /* =fr open(2): search */
+#define AUE_OPEN_E 118 /* =fr open(2): exec */
/*
- * 117 - 129 are available for future growth (old SunOS_CMW events
+ * 119 - 129 are available for future growth (old SunOS_CMW events
* that had no libbsm or praudit support or references)
*/
#define AUE_GETAUID 130 /* =aa getauid(2) */
diff --git a/usr/src/uts/common/fs/lookup.c b/usr/src/uts/common/fs/lookup.c
index 6d8e657959..6819509d00 100644
--- a/usr/src/uts/common/fs/lookup.c
+++ b/usr/src/uts/common/fs/lookup.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -63,7 +64,7 @@ int
lookupname(
char *fnamep,
enum uio_seg seg,
- enum symfollow followlink,
+ int followlink,
vnode_t **dirvpp,
vnode_t **compvpp)
{
@@ -79,7 +80,7 @@ int
lookupnameatcred(
char *fnamep, /* user pathname */
enum uio_seg seg, /* addr space that name is in */
- enum symfollow followlink, /* follow sym links */
+ int followlink, /* follow sym links */
vnode_t **dirvpp, /* ret for ptr to parent dir vnode */
vnode_t **compvpp, /* ret for ptr to component vnode */
vnode_t *startvp, /* start path search from vp */
@@ -109,7 +110,7 @@ lookupnameatcred(
}
int
-lookupnameat(char *fnamep, enum uio_seg seg, enum symfollow followlink,
+lookupnameat(char *fnamep, enum uio_seg seg, int followlink,
vnode_t **dirvpp, vnode_t **compvpp, vnode_t *startvp)
{
return (lookupnameatcred(fnamep, seg, followlink, dirvpp, compvpp,
@@ -120,7 +121,7 @@ int
lookuppn(
struct pathname *pnp,
struct pathname *rpnp,
- enum symfollow followlink,
+ int followlink,
vnode_t **dirvpp,
vnode_t **compvpp)
{
@@ -135,7 +136,7 @@ int
lookuppnatcred(
struct pathname *pnp, /* pathname to lookup */
struct pathname *rpnp, /* if non-NULL, return resolved path */
- enum symfollow followlink, /* (don't) follow sym links */
+ int followlink, /* (don't) follow sym links */
vnode_t **dirvpp, /* ptr for parent vnode */
vnode_t **compvpp, /* ptr for entry vnode */
vnode_t *startvp, /* start search from this vp */
@@ -178,7 +179,7 @@ lookuppnatcred(
int
lookuppnat(struct pathname *pnp, struct pathname *rpnp,
- enum symfollow followlink, vnode_t **dirvpp, vnode_t **compvpp,
+ int followlink, vnode_t **dirvpp, vnode_t **compvpp,
vnode_t *startvp)
{
return (lookuppnatcred(pnp, rpnp, followlink, dirvpp, compvpp, startvp,
diff --git a/usr/src/uts/common/fs/vnode.c b/usr/src/uts/common/fs/vnode.c
index 4c5e1b3da3..382369c7fc 100644
--- a/usr/src/uts/common/fs/vnode.c
+++ b/usr/src/uts/common/fs/vnode.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -965,7 +966,7 @@ vn_openat(
mode |= VREAD;
if (filemode & (FWRITE|FTRUNC))
mode |= VWRITE;
- if (filemode & FXATTRDIROPEN)
+ if (filemode & (FSEARCH|FEXEC|FXATTRDIROPEN))
mode |= VEXEC;
/* symlink interpretation */
@@ -1075,6 +1076,18 @@ top:
*/
if (error = VOP_ACCESS(vp, mode, accessflags, CRED(), NULL))
goto out;
+ /*
+ * Require FSEARCH to return a directory.
+ * Require FEXEC to return a regular file.
+ */
+ if ((filemode & FSEARCH) && vp->v_type != VDIR) {
+ error = ENOTDIR;
+ goto out;
+ }
+ if ((filemode & FEXEC) && vp->v_type != VREG) {
+ error = ENOEXEC; /* XXX: error code? */
+ goto out;
+ }
}
/*
@@ -1558,6 +1571,13 @@ out:
int
vn_link(char *from, char *to, enum uio_seg seg)
{
+ return (vn_linkat(NULL, from, NO_FOLLOW, NULL, to, seg));
+}
+
+int
+vn_linkat(vnode_t *fstartvp, char *from, enum symfollow follow,
+ vnode_t *tstartvp, char *to, enum uio_seg seg)
+{
struct vnode *fvp; /* from vnode ptr */
struct vnode *tdvp; /* to directory vnode ptr */
struct pathname pn;
@@ -1565,14 +1585,19 @@ vn_link(char *from, char *to, enum uio_seg seg)
struct vattr vattr;
dev_t fsid;
int estale_retry = 0;
+ uint32_t auditing = AU_AUDITING();
top:
fvp = tdvp = NULL;
if (error = pn_get(to, seg, &pn))
return (error);
- if (error = lookupname(from, seg, NO_FOLLOW, NULLVPP, &fvp))
+ if (auditing && fstartvp != NULL)
+ audit_setfsat_path(1);
+ if (error = lookupnameat(from, seg, follow, NULLVPP, &fvp, fstartvp))
goto out;
- if (error = lookuppn(&pn, NULL, NO_FOLLOW, &tdvp, NULLVPP))
+ if (auditing && tstartvp != NULL)
+ audit_setfsat_path(3);
+ if (error = lookuppnat(&pn, NULL, NO_FOLLOW, &tdvp, NULLVPP, tstartvp))
goto out;
/*
* Make sure both source vnode and target directory vnode are
@@ -1652,7 +1677,7 @@ top:
* use the lib directory for the rename.
*/
- if (auditing && (fdvp != NULL))
+ if (auditing && fdvp != NULL)
audit_setfsat_path(1);
/*
* Lookup to and from directories.
@@ -1669,7 +1694,7 @@ top:
goto out;
}
- if (auditing && (tdvp != NULL))
+ if (auditing && tdvp != NULL)
audit_setfsat_path(3);
if (error = lookuppnat(&tpn, NULL, NO_FOLLOW, &tovp, &targvp, tdvp)) {
goto out;
diff --git a/usr/src/uts/common/os/core.c b/usr/src/uts/common/os/core.c
index ece9d8f0eb..9e04f631a9 100644
--- a/usr/src/uts/common/os/core.c
+++ b/usr/src/uts/common/os/core.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -436,9 +435,6 @@ do_core(char *fp, int sig, enum core_types core_type, struct core_globals *cg)
#if defined(__sparc)
(void) flush_user_windows_to_stack(NULL);
#endif
-#ifdef SUN_SRC_COMPAT
- PTOU(curproc)->u_acflag |= ACORE;
-#endif
if ((eswp = PTOU(curproc)->u_execsw) == NULL ||
(eswp = findexec_by_magic(eswp->exec_magic)) == NULL) {
error = ENOSYS;
diff --git a/usr/src/uts/common/os/exit.c b/usr/src/uts/common/os/exit.c
index 5b9d682ce1..47dcb0b7f0 100644
--- a/usr/src/uts/common/os/exit.c
+++ b/usr/src/uts/common/os/exit.c
@@ -500,10 +500,6 @@ proc_exit(int why, int what)
*/
prbarrier(p);
-#ifdef SUN_SRC_COMPAT
- if (code == CLD_KILLED)
- u.u_acflag |= AXSIG;
-#endif
sigfillset(&p->p_ignore);
sigemptyset(&p->p_siginfo);
sigemptyset(&p->p_sig);
diff --git a/usr/src/uts/common/os/fio.c b/usr/src/uts/common/os/fio.c
index 4ba4ec7560..a014d25c0f 100644
--- a/usr/src/uts/common/os/fio.c
+++ b/usr/src/uts/common/os/fio.c
@@ -75,7 +75,6 @@ static uint32_t afd_wait; /* count of waits on non-zero ref count */
#endif /* DEBUG */
kmem_cache_t *file_cache;
-static int vpsetattr(vnode_t *, vattr_t *, int);
static void port_close_fd(portfd_t *);
@@ -1087,6 +1086,7 @@ falloc(vnode_t *vp, int flag, file_t **fpp, int *fdp)
mutex_enter(&fp->f_tlock);
fp->f_count = 1;
fp->f_flag = (ushort_t)flag;
+ fp->f_flag2 = (flag & (FSEARCH|FEXEC)) >> 16;
fp->f_vnode = vp;
fp->f_offset = 0;
fp->f_audit_data = 0;
@@ -1195,7 +1195,7 @@ f_getfl(int fd, int *flagp)
error = EBADF;
else {
vnode_t *vp = fp->f_vnode;
- int flag = fp->f_flag;
+ int flag = fp->f_flag | (fp->f_flag2 << 16);
/*
* BSD fcntl() FASYNC compatibility.
@@ -1460,85 +1460,107 @@ close_exec(uf_info_t *fip)
}
/*
- * Common routine for modifying attributes of named files.
+ * Utility function called by most of the *at() system call interfaces.
+ *
+ * Generate a starting vnode pointer for an (fd, path) pair where 'fd'
+ * is an open file descriptor for a directory to be used as the starting
+ * point for the lookup of the relative pathname 'path' (or, if path is
+ * NULL, generate a vnode pointer for the direct target of the operation).
+ *
+ * If we successfully return a non-NULL startvp, it has been the target
+ * of VN_HOLD() and the caller must call VN_RELE() on it.
*/
int
-namesetattr(char *fnamep, enum symfollow followlink, vattr_t *vap, int flags)
+fgetstartvp(int fd, char *path, vnode_t **startvpp)
{
- vnode_t *vp;
- int error = 0;
+ vnode_t *startvp;
+ file_t *startfp;
+ char startchar;
- if (error = lookupname(fnamep, UIO_USERSPACE, followlink, NULLVPP, &vp))
- return (set_errno(error));
- if (error = vpsetattr(vp, vap, flags))
- (void) set_errno(error);
- VN_RELE(vp);
- return (error);
-}
+ if (fd == AT_FDCWD && path == NULL)
+ return (EFAULT);
-/*
- * Common routine for modifying attributes of files referenced
- * by descriptor.
- */
-int
-fdsetattr(int fd, vattr_t *vap)
-{
- file_t *fp;
- vnode_t *vp;
- int error = 0;
+ if (fd == AT_FDCWD) {
+ /*
+ * Start from the current working directory.
+ */
+ startvp = NULL;
+ } else {
+ if (path == NULL)
+ startchar = '\0';
+ else if (copyin(path, &startchar, sizeof (char)))
+ return (EFAULT);
- if ((fp = getf(fd)) != NULL) {
- vp = fp->f_vnode;
- if (error = vpsetattr(vp, vap, 0)) {
- (void) set_errno(error);
+ if (startchar == '/') {
+ /*
+ * 'path' is an absolute pathname.
+ */
+ startvp = NULL;
+ } else {
+ /*
+ * 'path' is a relative pathname or we will
+ * be applying the operation to 'fd' itself.
+ */
+ if ((startfp = getf(fd)) == NULL)
+ return (EBADF);
+ startvp = startfp->f_vnode;
+ VN_HOLD(startvp);
+ releasef(fd);
}
- releasef(fd);
- } else
- error = set_errno(EBADF);
- return (error);
+ }
+ *startvpp = startvp;
+ return (0);
}
/*
- * Common routine to set the attributes for the given vnode.
- * If the vnode is a file and the filesize is being manipulated,
- * this makes sure that there are no conflicting non-blocking
- * mandatory locks in that region.
+ * Called from fchownat() and fchmodat() to set ownership and mode.
+ * The contents of *vap must be set before calling here.
*/
-static int
-vpsetattr(vnode_t *vp, vattr_t *vap, int flags)
+int
+fsetattrat(int fd, char *path, int flags, struct vattr *vap)
{
- int error = 0;
- int in_crit = 0;
- u_offset_t begin;
- vattr_t vattr;
- ssize_t length;
+ vnode_t *startvp;
+ vnode_t *vp;
+ int error;
+
+ /*
+ * Since we are never called to set the size of a file, we don't
+ * need to check for non-blocking locks (via nbl_need_check(vp)).
+ */
+ ASSERT(!(vap->va_mask & AT_SIZE));
+
+ if ((error = fgetstartvp(fd, path, &startvp)) != 0)
+ return (error);
+ if (AU_AUDITING() && startvp != NULL)
+ audit_setfsat_path(1);
+
+ /*
+ * Do lookup for fchownat/fchmodat when path not NULL
+ */
+ if (path != NULL) {
+ if (error = lookupnameat(path, UIO_USERSPACE,
+ (flags == AT_SYMLINK_NOFOLLOW) ?
+ NO_FOLLOW : FOLLOW,
+ NULLVPP, &vp, startvp)) {
+ if (startvp != NULL)
+ VN_RELE(startvp);
+ return (error);
+ }
+ } else {
+ vp = startvp;
+ ASSERT(vp);
+ VN_HOLD(vp);
+ }
if (vn_is_readonly(vp)) {
error = EROFS;
+ } else {
+ error = VOP_SETATTR(vp, vap, 0, CRED(), NULL);
}
- if (!error && (vap->va_mask & AT_SIZE) &&
- nbl_need_check(vp)) {
- nbl_start_crit(vp, RW_READER);
- in_crit = 1;
- vattr.va_mask = AT_SIZE;
- if (!(error = VOP_GETATTR(vp, &vattr, 0, CRED(), NULL))) {
- begin = vap->va_size > vattr.va_size ?
- vattr.va_size : vap->va_size;
- length = vattr.va_size > vap->va_size ?
- vattr.va_size - vap->va_size :
- vap->va_size - vattr.va_size;
-
- if (nbl_conflict(vp, NBL_WRITE, begin, length, 0,
- NULL)) {
- error = EACCES;
- }
- }
- }
- if (!error)
- error = VOP_SETATTR(vp, vap, flags, CRED(), NULL);
- if (in_crit)
- nbl_end_crit(vp);
+ if (startvp != NULL)
+ VN_RELE(startvp);
+ VN_RELE(vp);
return (error);
}
diff --git a/usr/src/uts/common/os/sysent.c b/usr/src/uts/common/os/sysent.c
index b956756758..7a40be6d9e 100644
--- a/usr/src/uts/common/os/sysent.c
+++ b/usr/src/uts/common/os/sysent.c
@@ -20,6 +20,7 @@
*/
/* ONC_PLUS EXTRACT START */
+
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -58,6 +59,7 @@ int cladm();
int close();
int exece();
int faccessat();
+int fchmodat();
int fchownat();
int fcntl();
int64_t vfork();
@@ -80,11 +82,13 @@ int ioctl();
int kill();
int labelsys();
int link();
+int linkat();
off32_t lseek32();
off_t lseek64();
int lgrpsys();
int mmapobjsys();
int mknod();
+int mknodat();
int mount();
int nice();
int nullsys();
@@ -139,6 +143,7 @@ ssize_t writev();
int syslwp_park();
int rmdir();
int mkdir();
+int mkdirat();
int getdents32();
int statfs32();
int fstatfs32();
@@ -149,7 +154,9 @@ int putmsg();
int uadmin();
int lstat();
int symlink();
+int symlinkat();
ssize_t readlink();
+ssize_t readlinkat();
int resolvepath();
int setgroups();
int getgroups();
@@ -423,11 +430,11 @@ struct sysent sysent[NSYSCALL] =
/* 4 */ SYSENT_CL("write", write, 3),
/* 5 */ SYSENT_CI("open", open, 3),
/* 6 */ SYSENT_CI("close", close, 1),
- /* 7 */ SYSENT_LOADABLE(), /* (was wait) */
+ /* 7 */ SYSENT_CI("linkat", linkat, 5),
/* 8 */ SYSENT_LOADABLE(), /* (was creat) */
/* 9 */ SYSENT_CI("link", link, 2),
/* 10 */ SYSENT_CI("unlink", unlink, 1),
- /* 11 */ SYSENT_LOADABLE(), /* (was exec) */
+ /* 11 */ SYSENT_CI("symlinkat", symlinkat, 3),
/* 12 */ SYSENT_CI("chdir", chdir, 1),
/* 13 */ SYSENT_CL("time", gtime, 0),
/* 14 */ SYSENT_CI("mknod", mknod, 3),
@@ -440,7 +447,7 @@ struct sysent sysent[NSYSCALL] =
SYSENT_CL("lseek", lseek32, 3)),
/* 20 */ SYSENT_2CI("getpid", getpid, 0),
/* 21 */ SYSENT_AP("mount", mount, 8),
- /* 22 */ SYSENT_LOADABLE(), /* (was umount) */
+ /* 22 */ SYSENT_CL("readlinkat", readlinkat, 4),
/* 23 */ SYSENT_CI("setuid", setuid, 1),
/* 24 */ SYSENT_2CI("getuid", getuid, 0),
/* 25 */ SYSENT_CI("stime", stime, 1),
@@ -470,7 +477,7 @@ struct sysent sysent[NSYSCALL] =
/* 45 */ SYSENT_CI("faccessat", faccessat, 4),
/* 46 */ SYSENT_CI("setgid", setgid, 1),
/* 47 */ SYSENT_2CI("getgid", getgid, 0),
- /* 48 */ SYSENT_LOADABLE(), /* (was ssig) */
+ /* 48 */ SYSENT_CI("mknodat", mknodat, 4),
/* 49 */ SYSENT_LOADABLE(), /* msgsys */
/* 50 */ IF_x86(
SYSENT_CI("sysi86", sysi86, 4),
@@ -533,8 +540,8 @@ struct sysent sysent[NSYSCALL] =
/* 98 */ SYSENT_CI("sigaction", sigaction, 3),
/* 99 */ SYSENT_CI("sigpending", sigpending, 2),
/* 100 */ SYSENT_CI("getsetcontext", getsetcontext, 2),
- /* 101 */ SYSENT_LOADABLE(),
- /* 102 */ SYSENT_LOADABLE(),
+ /* 101 */ SYSENT_CI("fchmodat", fchmodat, 4),
+ /* 102 */ SYSENT_CI("mkdirat", mkdirat, 3),
/* 103 */ SYSENT_CI("statvfs", statvfs, 2),
/* 104 */ SYSENT_CI("fstatvfs", fstatvfs, 2),
/* 105 */ SYSENT_CI("getloadavg", getloadavg, 2),
@@ -754,6 +761,7 @@ extern ssize_t pwrite32();
extern ssize_t readv32();
extern ssize_t writev32();
extern ssize_t readlink32();
+extern ssize_t readlinkat32();
extern int open32();
extern int openat32();
extern int stat32();
@@ -805,11 +813,11 @@ struct sysent sysent32[NSYSCALL] =
/* 4 */ SYSENT_CI("write", write32, 3),
/* 5 */ SYSENT_CI("open", open32, 3),
/* 6 */ SYSENT_CI("close", close, 1),
- /* 7 */ SYSENT_LOADABLE32(), /* (was wait) */
+ /* 7 */ SYSENT_CI("linkat", linkat, 5),
/* 8 */ SYSENT_LOADABLE32(), /* (was creat32) */
/* 9 */ SYSENT_CI("link", link, 2),
/* 10 */ SYSENT_CI("unlink", unlink, 1),
- /* 11 */ SYSENT_LOADABLE32(), /* (was exec) */
+ /* 11 */ SYSENT_CI("symlinkat", symlinkat, 3),
/* 12 */ SYSENT_CI("chdir", chdir, 1),
/* 13 */ SYSENT_CI("time", gtime, 0),
/* 14 */ SYSENT_CI("mknod", mknod, 3),
@@ -820,7 +828,7 @@ struct sysent sysent32[NSYSCALL] =
/* 19 */ SYSENT_CI("lseek", lseek32, 3),
/* 20 */ SYSENT_2CI("getpid", getpid, 0),
/* 21 */ SYSENT_AP("mount", mount, 8),
- /* 22 */ SYSENT_LOADABLE32(), /* (was umount) */
+ /* 22 */ SYSENT_CI("readlinkat", readlinkat32, 4),
/* 23 */ SYSENT_CI("setuid", setuid, 1),
/* 24 */ SYSENT_2CI("getuid", getuid, 0),
/* 25 */ SYSENT_CI("stime", stime32, 1),
@@ -846,7 +854,7 @@ struct sysent sysent32[NSYSCALL] =
/* 45 */ SYSENT_CI("faccessat", faccessat, 4),
/* 46 */ SYSENT_CI("setgid", setgid, 1),
/* 47 */ SYSENT_2CI("getgid", getgid, 0),
- /* 48 */ SYSENT_LOADABLE32(), /* (was ssig) */
+ /* 48 */ SYSENT_CI("mknodat", mknodat, 4),
/* 49 */ SYSENT_LOADABLE32(), /* msgsys */
/* 50 */ IF_386_ABI(
SYSENT_CI("sysi86", sysi86, 4),
@@ -901,8 +909,8 @@ struct sysent sysent32[NSYSCALL] =
/* 98 */ SYSENT_CI("sigaction", sigaction32, 3),
/* 99 */ SYSENT_CI("sigpending", sigpending, 2),
/* 100 */ SYSENT_CI("getsetcontext", getsetcontext32, 2),
- /* 101 */ SYSENT_LOADABLE32(),
- /* 102 */ SYSENT_LOADABLE32(),
+ /* 101 */ SYSENT_CI("fchmodat", fchmodat, 4),
+ /* 102 */ SYSENT_CI("mkdirat", mkdirat, 3),
/* 103 */ SYSENT_CI("statvfs", statvfs32, 2),
/* 104 */ SYSENT_CI("fstatvfs", fstatvfs32, 2),
/* 105 */ SYSENT_CI("getloadavg", getloadavg, 2),
diff --git a/usr/src/uts/common/sys/acct.h b/usr/src/uts/common/sys/acct.h
index 7853af96f0..e8903bd0da 100644
--- a/usr/src/uts/common/sys/acct.h
+++ b/usr/src/uts/common/sys/acct.h
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,20 +18,17 @@
*
* CDDL HEADER END
*/
-/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
-/* All Rights Reserved */
-
/*
- * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
#ifndef _SYS_ACCT_H
#define _SYS_ACCT_H
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/types.h>
#include <sys/types32.h>
@@ -104,11 +100,6 @@ int acct_fs_in_use(struct vnode *);
#define AFORK 0001 /* has executed fork, but no exec */
#define ASU 0002 /* used super-user privileges */
-#ifdef SUN_SRC_COMPAT
-#define ACOMPAT 0004 /* used compatibility mode (VAX) */
-#define ACORE 0010 /* dumped core */
-#define AXSIG 0020 /* killed by a signal */
-#endif /* SUN_SRC_COMPAT */
#define AEXPND 0040 /* expanded acct structure */
#define ACCTF 0300 /* record type: 00 = acct */
diff --git a/usr/src/uts/common/sys/fcntl.h b/usr/src/uts/common/sys/fcntl.h
index 9057a671a6..a0c4191b1c 100644
--- a/usr/src/uts/common/sys/fcntl.h
+++ b/usr/src/uts/common/sys/fcntl.h
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -50,11 +49,13 @@ extern "C" {
/*
* Flag values accessible to open(2) and fcntl(2)
- * (the first three can only be set by open(2)).
+ * The first five can only be set (exclusively) by open(2).
*/
#define O_RDONLY 0
#define O_WRONLY 1
#define O_RDWR 2
+#define O_SEARCH 0x200000
+#define O_EXEC 0x400000
#if defined(__EXTENSIONS__) || !defined(_POSIX_C_SOURCE)
#define O_NDELAY 0x04 /* non-blocking I/O */
#endif /* defined(__EXTENSIONS__) || !defined(_POSIX_C_SOURCE) */
@@ -67,9 +68,6 @@ extern "C" {
/* defines read/write file integrity */
#endif /* defined(__EXTENSIONS__) || !defined(_POSIX_C_SOURCE) ... */
#define O_NONBLOCK 0x80 /* non-blocking I/O (POSIX) */
-#ifdef SUN_SRC_COMPAT
-#define O_PRIV 0x1000 /* Private access to file */
-#endif /* SUN_SRC_COMPAT */
#ifdef _LARGEFILE_SOURCE
#define O_LARGEFILE 0x2000
#endif
@@ -300,7 +298,8 @@ typedef struct o_flock {
* POSIX constants
*/
-#define O_ACCMODE 3 /* Mask for file access modes */
+/* Mask for file access modes */
+#define O_ACCMODE (O_SEARCH | O_EXEC | 0x3)
#define FD_CLOEXEC 1 /* close on exec flag */
/*
@@ -345,8 +344,10 @@ typedef struct fshare {
*/
#if !defined(__XOPEN_OR_POSIX) || defined(_ATFILE_SOURCE) || \
defined(__EXTENSIONS__)
+ /* || defined(_XPG7) */
#define AT_FDCWD 0xffd19553
#define AT_SYMLINK_NOFOLLOW 0x1000
+#define AT_SYMLINK_FOLLOW 0x2000 /* only for linkat() */
#define AT_REMOVEDIR 0x1
#define _AT_TRIGGER 0x2
#define AT_EACCESS 0x4 /* use EUID/EGID for access */
diff --git a/usr/src/uts/common/sys/file.h b/usr/src/uts/common/sys/file.h
index 494840aff8..f402bc7079 100644
--- a/usr/src/uts/common/sys/file.h
+++ b/usr/src/uts/common/sys/file.h
@@ -18,20 +18,17 @@
*
* CDDL HEADER END
*/
-/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
-/* All Rights Reserved */
-
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
+/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
+/* All Rights Reserved */
+
#ifndef _SYS_FILE_H
#define _SYS_FILE_H
-#pragma ident "%Z%%M% %I% %E% SMI" /* SVr4.0 11.28 */
-
#include <sys/t_lock.h>
#ifdef _KERNEL
#include <sys/model.h>
@@ -61,7 +58,7 @@ extern "C" {
typedef struct file {
kmutex_t f_tlock; /* short term lock */
ushort_t f_flag;
- ushort_t f_pad; /* Explicit pad to 4 byte boundary */
+ ushort_t f_flag2; /* extra flags (FSEARCH, FEXEC) */
struct vnode *f_vnode; /* pointer to vnode structure */
offset_t f_offset; /* read/write character pointer */
struct cred *f_cred; /* credentials of user who opened it */
@@ -77,7 +74,7 @@ typedef struct fpollinfo {
struct fpollinfo *fp_next;
} fpollinfo_t;
-/* flags */
+/* f_flag */
#define FOPEN 0xffffffff
#define FREAD 0x01 /* <sys/aiocb.h> LIO_READ must be identical */
@@ -111,6 +108,11 @@ typedef struct fpollinfo {
#define FIGNORECASE 0x80000 /* request case-insensitive lookups */
#define FXATTRDIROPEN 0x100000 /* only opening hidden attribute directory */
+/* f_flag2 (open-only) */
+
+#define FSEARCH 0x200000 /* O_SEARCH = 0x200000 */
+#define FEXEC 0x400000 /* O_EXEC = 0x400000 */
+
#ifdef _KERNEL
/*
@@ -170,6 +172,7 @@ typedef struct fpollinfo {
*/
struct proc; /* forward reference for function prototype */
struct vnodeops;
+struct vattr;
extern file_t *getf(int);
extern void releasef(int);
@@ -199,6 +202,8 @@ extern void close_exec(uf_info_t *);
extern void clear_stale_fd(void);
extern void clear_active_fd(int);
extern void free_afd(afd_t *afd);
+extern int fgetstartvp(int, char *, struct vnode **);
+extern int fsetattrat(int, char *, int, struct vattr *);
extern int fisopen(struct vnode *);
extern void delfpollinfo(int);
extern void addfpollinfo(int);
diff --git a/usr/src/uts/common/sys/pathname.h b/usr/src/uts/common/sys/pathname.h
index 305e3cf09c..db978c1ea9 100644
--- a/usr/src/uts/common/sys/pathname.h
+++ b/usr/src/uts/common/sys/pathname.h
@@ -18,9 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -80,17 +80,17 @@ extern int pn_fixslash(struct pathname *);
extern int pn_addslash(struct pathname *);
extern void pn_free(struct pathname *);
-extern int lookupname(char *, enum uio_seg, enum symfollow,
+extern int lookupname(char *, enum uio_seg, int follow,
vnode_t **, vnode_t **);
-extern int lookupnameat(char *, enum uio_seg, enum symfollow,
+extern int lookupnameat(char *, enum uio_seg, int follow,
vnode_t **, vnode_t **, vnode_t *);
-extern int lookupnameatcred(char *, enum uio_seg, enum symfollow,
+extern int lookupnameatcred(char *, enum uio_seg, int follow,
vnode_t **, vnode_t **, vnode_t *, cred_t *);
-extern int lookuppn(struct pathname *, struct pathname *, enum symfollow,
+extern int lookuppn(struct pathname *, struct pathname *, int follow,
vnode_t **, vnode_t **);
-extern int lookuppnat(struct pathname *, struct pathname *, enum symfollow,
+extern int lookuppnat(struct pathname *, struct pathname *, int follow,
vnode_t **, vnode_t **, vnode_t *);
-extern int lookuppnatcred(struct pathname *, struct pathname *, enum symfollow,
+extern int lookuppnatcred(struct pathname *, struct pathname *, int follow,
vnode_t **, vnode_t **, vnode_t *, cred_t *);
extern int lookuppnvp(struct pathname *, struct pathname *, int follow,
diff --git a/usr/src/uts/common/sys/stat.h b/usr/src/uts/common/sys/stat.h
index 81fb9e4ab8..3f68a55730 100644
--- a/usr/src/uts/common/sys/stat.h
+++ b/usr/src/uts/common/sys/stat.h
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
@@ -505,9 +504,13 @@ extern int fstatat64(int, const char *, struct stat64 *, int);
#endif /* defined (_ATFILE_SOURCE) */
#endif
-#if defined(__EXTENSIONS__) || \
+#if defined(__EXTENSIONS__) || defined(_ATFILE_SOURCE) || \
(!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX))
/* || defined(_XPG7) */
+extern int mkdirat(int, const char *, mode_t);
+extern int mkfifoat(int, const char *, mode_t);
+extern int mknodat(int, const char *, mode_t, dev_t);
+extern int fchmodat(int, const char *, mode_t, int);
extern int futimens(int, const struct timespec[2]);
extern int utimensat(int, const char *, const struct timespec[2], int);
#endif /* defined(__EXTENSIONS__) ... */
@@ -536,9 +539,13 @@ extern int fstatat64();
#endif /* defined (_ATFILE_SOURCE) */
#endif
-#if defined(__EXTENSIONS__) || \
+#if defined(__EXTENSIONS__) || defined(_ATFILE_SOURCE) || \
(!defined(_STRICT_STDC) && !defined(__XOPEN_OR_POSIX))
/* || defined(_XPG7) */
+extern int mkdirat();
+extern int mkfifoat();
+extern int mknodat();
+extern int fchmodat();
extern int futimens();
extern int utimensat();
#endif /* defined(__EXTENSIONS__) ... */
diff --git a/usr/src/uts/common/sys/syscall.h b/usr/src/uts/common/sys/syscall.h
index 170483de8d..633bfef143 100644
--- a/usr/src/uts/common/sys/syscall.h
+++ b/usr/src/uts/common/sys/syscall.h
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
@@ -53,8 +52,10 @@ extern "C" {
#define SYS_write 4
#define SYS_open 5
#define SYS_close 6
+#define SYS_linkat 7
#define SYS_link 9
#define SYS_unlink 10
+#define SYS_symlinkat 11
#define SYS_chdir 12
#define SYS_time 13
#define SYS_mknod 14
@@ -65,6 +66,7 @@ extern "C" {
#define SYS_lseek 19
#define SYS_getpid 20
#define SYS_mount 21
+#define SYS_readlinkat 22
#define SYS_setuid 23
#define SYS_getuid 24
#define SYS_stime 25
@@ -97,6 +99,7 @@ extern "C" {
#define SYS_faccessat 45
#define SYS_setgid 46
#define SYS_getgid 47
+#define SYS_mknodat 48
#define SYS_msgsys 49
/*
* subcodes:
@@ -260,6 +263,8 @@ extern "C" {
* getcontext(...) :: syscall(100, 0, ...)
* setcontext(...) :: syscall(100, 1, ...)
*/
+#define SYS_fchmodat 101
+#define SYS_mkdirat 102
#define SYS_statvfs 103
#define SYS_fstatvfs 104
#define SYS_getloadavg 105
diff --git a/usr/src/uts/common/sys/vnode.h b/usr/src/uts/common/sys/vnode.h
index 1fbcb29005..b34eb6b4ff 100644
--- a/usr/src/uts/common/sys/vnode.h
+++ b/usr/src/uts/common/sys/vnode.h
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 1988, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -1159,7 +1160,7 @@ extern int fop_retzcbuf(vnode_t *, xuio_t *, cred_t *, caller_context_t *);
/*
* Flags for VOP_LOOKUP
*
- * Defined in file.h, but also possible, FIGNORECASE
+ * Defined in file.h, but also possible, FIGNORECASE and FSEARCH
*
*/
#define LOOKUP_DIR 0x01 /* want parent dir vp */
@@ -1244,6 +1245,8 @@ void vn_rele_async(struct vnode *vp, struct taskq *taskq);
void vn_rele_dnlc(struct vnode *vp);
void vn_rele_stream(struct vnode *vp);
int vn_link(char *from, char *to, enum uio_seg seg);
+int vn_linkat(vnode_t *fstartvp, char *from, enum symfollow follow,
+ vnode_t *tstartvp, char *to, enum uio_seg seg);
int vn_rename(char *from, char *to, enum uio_seg seg);
int vn_renameat(vnode_t *fdvp, char *fname, vnode_t *tdvp, char *tname,
enum uio_seg seg);
diff --git a/usr/src/uts/common/syscall/access.c b/usr/src/uts/common/syscall/access.c
index 9e4f1aac84..a6bda94367 100644
--- a/usr/src/uts/common/syscall/access.c
+++ b/usr/src/uts/common/syscall/access.c
@@ -18,6 +18,7 @@
*
* CDDL HEADER END
*/
+
/*
* Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
*/
@@ -68,7 +69,7 @@ caccess(char *fname, int fmode, vnode_t *startvp)
int estale_retry = 0;
if (fmode & ~(E_OK|R_OK|W_OK|X_OK))
- return (set_errno(EINVAL));
+ return (EINVAL);
mode = ((fmode & (R_OK|W_OK|X_OK)) << 6);
@@ -95,7 +96,7 @@ lookup:
goto lookup;
if (!eok)
crfree(tmpcr);
- return (set_errno(error));
+ return (error);
}
if (mode) {
@@ -106,7 +107,6 @@ lookup:
VN_RELE(vp);
goto lookup;
}
- (void) set_errno(error);
}
}
@@ -119,39 +119,17 @@ lookup:
int
faccessat(int fd, char *fname, int fmode, int flag)
{
- file_t *dirfp;
- vnode_t *dirvp;
+ vnode_t *startvp;
int error;
- char startchar;
-
- if (fd == AT_FDCWD && fname == NULL)
- return (set_errno(EFAULT));
if ((flag & ~AT_EACCESS) != 0)
return (set_errno(EINVAL));
- if (fname != NULL) {
- if (copyin(fname, &startchar, sizeof (char)))
- return (set_errno(EFAULT));
- } else
- startchar = '\0';
-
- if (fd == AT_FDCWD) {
- dirvp = NULL;
- } else {
- if (startchar != '/') {
- if ((dirfp = getf(fd)) == NULL) {
- return (set_errno(EBADF));
- }
- dirvp = dirfp->f_vnode;
- VN_HOLD(dirvp);
- releasef(fd);
- } else {
- dirvp = NULL;
- }
- }
-
- if (AU_AUDITING() && (dirvp != NULL))
+ if (fname == NULL)
+ return (set_errno(EFAULT));
+ if ((error = fgetstartvp(fd, fname, &startvp)) != 0)
+ return (set_errno(error));
+ if (AU_AUDITING() && startvp != NULL)
audit_setfsat_path(1);
/* Do not allow E_OK unless AT_EACCESS flag is set */
@@ -159,11 +137,12 @@ faccessat(int fd, char *fname, int fmode, int flag)
if (flag & AT_EACCESS)
fmode |= E_OK;
- error = caccess(fname, fmode, dirvp);
- if (dirvp != NULL)
- VN_RELE(dirvp);
-
- return (error);
+ error = caccess(fname, fmode, startvp);
+ if (startvp != NULL)
+ VN_RELE(startvp);
+ if (error)
+ return (set_errno(error));
+ return (0);
}
int
diff --git a/usr/src/uts/common/syscall/chmod.c b/usr/src/uts/common/syscall/chmod.c
index 8fb42e0843..bed521f0b3 100644
--- a/usr/src/uts/common/syscall/chmod.c
+++ b/usr/src/uts/common/syscall/chmod.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,21 +18,14 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 1989 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
-/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- */
-
-#ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/isa_defs.h>
#include <sys/types.h>
@@ -51,31 +43,43 @@
#include <sys/filio.h>
#include <sys/debug.h>
-extern int namesetattr(char *, enum symfollow, vattr_t *, int);
-extern int fdsetattr(int, vattr_t *);
-
/*
- * Change mode of file given path name.
+ * Change mode of file.
*/
int
-chmod(char *fname, int fmode)
+fchmodat(int fd, char *path, int mode, int flag)
{
struct vattr vattr;
+ int error;
+
+ if (flag & ~AT_SYMLINK_NOFOLLOW)
+ return (set_errno(EINVAL));
- vattr.va_mode = fmode & MODEMASK;
+ if (flag & AT_SYMLINK_NOFOLLOW)
+ return (set_errno(EOPNOTSUPP));
+
+ vattr.va_mode = mode & MODEMASK;
vattr.va_mask = AT_MODE;
- return (namesetattr(fname, FOLLOW, &vattr, 0));
+ error = fsetattrat(fd, path, flag, &vattr);
+ if (error)
+ return (set_errno(error));
+ return (0);
}
/*
- * Change mode of file given file descriptor.
+ * Change mode of file given path name.
*/
int
-fchmod(int fd, int fmode)
+chmod(char *path, int mode)
{
- struct vattr vattr;
+ return (fchmodat(AT_FDCWD, path, mode, 0));
+}
- vattr.va_mode = fmode & MODEMASK;
- vattr.va_mask = AT_MODE;
- return (fdsetattr(fd, &vattr));
+/*
+ * Change mode of file given file descriptor.
+ */
+int
+fchmod(int fd, int mode)
+{
+ return (fchmodat(fd, NULL, mode, 0));
}
diff --git a/usr/src/uts/common/syscall/chown.c b/usr/src/uts/common/syscall/chown.c
index ccb0b584ee..40c76e61bc 100644
--- a/usr/src/uts/common/syscall/chown.c
+++ b/usr/src/uts/common/syscall/chown.c
@@ -55,13 +55,10 @@
* Change ownership of file.
*/
int
-fchownat(int fd, char *name, uid_t uid, gid_t gid, int flags)
+fchownat(int fd, char *path, uid_t uid, gid_t gid, int flag)
{
- vnode_t *startvp, *vp;
- file_t *filefp;
struct vattr vattr;
- int error = 0;
- char startchar;
+ int error;
struct zone *zone = crgetzone(CRED());
if (uid != (uid_t)-1 && !VALID_UID(uid, zone) ||
@@ -76,83 +73,22 @@ fchownat(int fd, char *name, uid_t uid, gid_t gid, int flags)
if (vattr.va_gid != -1)
vattr.va_mask |= AT_GID;
-
- if (fd == AT_FDCWD && name == NULL)
- return (set_errno(EFAULT));
-
- if (name != NULL) {
- if (copyin(name, &startchar, sizeof (char)))
- return (set_errno(EFAULT));
- } else {
- startchar = '\0';
- }
-
-
- if (fd == AT_FDCWD)
- startvp = NULL;
- else {
- /*
- * only get fd if not doing absolute lookup
- */
- if (startchar != '/') {
- if ((filefp = getf(fd)) == NULL)
- return (set_errno(EBADF));
- startvp = filefp->f_vnode;
- VN_HOLD(startvp);
- releasef(fd);
- } else {
- startvp = NULL;
- }
- }
-
- if (AU_AUDITING() && (startvp != NULL))
- audit_setfsat_path(1);
-
- /*
- * Do lookup for fchownat when name not NULL
- */
- if (name != NULL) {
- if (error = lookupnameat(name, UIO_USERSPACE,
- (flags == AT_SYMLINK_NOFOLLOW) ?
- NO_FOLLOW : FOLLOW,
- NULLVPP, &vp, startvp)) {
- if (startvp != NULL)
- VN_RELE(startvp);
- return (set_errno(error));
- }
- } else {
- vp = startvp;
- ASSERT(vp);
- VN_HOLD(vp);
- }
-
- if (vn_is_readonly(vp)) {
- error = EROFS;
- } else {
- error = VOP_SETATTR(vp, &vattr, 0, CRED(), NULL);
- }
-
- if (startvp != NULL)
- VN_RELE(startvp);
- if (vp != NULL)
- VN_RELE(vp);
-
- if (error != 0)
+ error = fsetattrat(fd, path, flag, &vattr);
+ if (error)
return (set_errno(error));
- else
- return (error);
+ return (0);
}
int
-chown(char *fname, uid_t uid, gid_t gid)
+chown(char *path, uid_t uid, gid_t gid)
{
- return (fchownat(AT_FDCWD, fname, uid, gid, 0));
+ return (fchownat(AT_FDCWD, path, uid, gid, 0));
}
int
-lchown(char *fname, uid_t uid, gid_t gid)
+lchown(char *path, uid_t uid, gid_t gid)
{
- return (fchownat(AT_FDCWD, fname, uid, gid, AT_SYMLINK_NOFOLLOW));
+ return (fchownat(AT_FDCWD, path, uid, gid, AT_SYMLINK_NOFOLLOW));
}
int
diff --git a/usr/src/uts/common/syscall/fcntl.c b/usr/src/uts/common/syscall/fcntl.c
index 0750e54697..4a6e58f6b0 100644
--- a/usr/src/uts/common/syscall/fcntl.c
+++ b/usr/src/uts/common/syscall/fcntl.c
@@ -114,13 +114,21 @@ fcntl(int fdes, int cmd, intptr_t arg)
goto out;
case F_GETFL:
- if ((error = f_getfl(fdes, &flag)) == 0)
- retval = (flag & (FMASK | FASYNC)) + FOPEN;
+ if ((error = f_getfl(fdes, &flag)) == 0) {
+ retval = (flag & (FMASK | FASYNC));
+ if ((flag & (FSEARCH | FEXEC)) == 0)
+ retval += FOPEN;
+ else
+ retval |= (flag & (FSEARCH | FEXEC));
+ }
goto out;
case F_GETXFL:
- if ((error = f_getfl(fdes, &flag)) == 0)
- retval = flag + FOPEN;
+ if ((error = f_getfl(fdes, &flag)) == 0) {
+ retval = flag;
+ if ((flag & (FSEARCH | FEXEC)) == 0)
+ retval += FOPEN;
+ }
goto out;
case F_BADFD:
diff --git a/usr/src/uts/common/syscall/getdents.c b/usr/src/uts/common/syscall/getdents.c
index da91808e74..944c9321aa 100644
--- a/usr/src/uts/common/syscall/getdents.c
+++ b/usr/src/uts/common/syscall/getdents.c
@@ -18,9 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -93,6 +93,10 @@ getdents32(int fd, void *buf, size_t count)
releasef(fd);
return (set_errno(ENOTDIR));
}
+ if (!(fp->f_flag & FREAD)) {
+ releasef(fd);
+ return (set_errno(EBADF));
+ }
/*
* Don't let the user overcommit kernel resources.
@@ -207,6 +211,10 @@ getdents64(int fd, void *buf, size_t count)
releasef(fd);
return (set_errno(ENOTDIR));
}
+ if (!(fp->f_flag & FREAD)) {
+ releasef(fd);
+ return (set_errno(EBADF));
+ }
aiov.iov_base = buf;
aiov.iov_len = count;
auio.uio_iov = &aiov;
diff --git a/usr/src/uts/common/syscall/link.c b/usr/src/uts/common/syscall/link.c
index a63b04f133..5e6522ce8d 100644
--- a/usr/src/uts/common/syscall/link.c
+++ b/usr/src/uts/common/syscall/link.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -19,9 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 1989 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -32,8 +31,6 @@
* under license from the Regents of the University of California.
*/
-#ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/isa_defs.h>
#include <sys/types.h>
@@ -41,18 +38,48 @@
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/vnode.h>
+#include <sys/file.h>
+#include <sys/fcntl.h>
#include <sys/uio.h>
#include <sys/debug.h>
+#include <c2/audit.h>
/*
* Make a hard link.
*/
int
-link(char *from, char *to)
+linkat(int ffd, char *from, int tfd, char *to, int flag)
{
- int error;
+ vnode_t *fstartvp = NULL;
+ vnode_t *tstartvp = NULL;
+ enum symfollow follow;
+ int error;
+
+ if (flag & ~AT_SYMLINK_FOLLOW)
+ return (set_errno(EINVAL));
+ follow = (flag & AT_SYMLINK_FOLLOW)? FOLLOW : NO_FOLLOW;
+
+ if (from == NULL || to == NULL)
+ return (set_errno(EFAULT));
+ if ((error = fgetstartvp(ffd, from, &fstartvp)) != 0)
+ goto out;
+ if ((error = fgetstartvp(tfd, to, &tstartvp)) != 0)
+ goto out;
+
+ error = vn_linkat(fstartvp, from, follow, tstartvp, to, UIO_USERSPACE);
- if (error = vn_link(from, to, UIO_USERSPACE))
+out:
+ if (fstartvp != NULL)
+ VN_RELE(fstartvp);
+ if (tstartvp != NULL)
+ VN_RELE(tstartvp);
+ if (error)
return (set_errno(error));
return (0);
}
+
+int
+link(char *from, char *to)
+{
+ return (linkat(AT_FDCWD, from, AT_FDCWD, to, 0));
+}
diff --git a/usr/src/uts/common/syscall/mkdir.c b/usr/src/uts/common/syscall/mkdir.c
index ef50e5a99d..ce21aaffc2 100644
--- a/usr/src/uts/common/syscall/mkdir.c
+++ b/usr/src/uts/common/syscall/mkdir.c
@@ -20,11 +20,9 @@
*/
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
*/
-
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
@@ -33,8 +31,6 @@
* under license from the Regents of the University of California.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/isa_defs.h>
#include <sys/types.h>
@@ -43,15 +39,19 @@
#include <sys/user.h>
#include <sys/errno.h>
#include <sys/vnode.h>
+#include <sys/file.h>
+#include <sys/fcntl.h>
#include <sys/uio.h>
#include <sys/debug.h>
+#include <c2/audit.h>
/*
* Make a directory.
*/
int
-mkdir(char *dname, int dmode)
+mkdirat(int fd, char *dname, int dmode)
{
+ vnode_t *startvp;
vnode_t *vp;
struct vattr vattr;
int error;
@@ -59,10 +59,26 @@ mkdir(char *dname, int dmode)
vattr.va_type = VDIR;
vattr.va_mode = dmode & PERMMASK;
vattr.va_mask = AT_TYPE|AT_MODE;
- error = vn_create(dname, UIO_USERSPACE, &vattr, EXCL, 0, &vp, CRMKDIR,
- 0, PTOU(curproc)->u_cmask);
+
+ if (dname == NULL)
+ return (set_errno(EFAULT));
+ if ((error = fgetstartvp(fd, dname, &startvp)) != 0)
+ return (set_errno(error));
+ if (AU_AUDITING() && startvp != NULL)
+ audit_setfsat_path(1);
+
+ error = vn_createat(dname, UIO_USERSPACE, &vattr, EXCL, 0, &vp,
+ CRMKDIR, 0, PTOU(curproc)->u_cmask, startvp);
+ if (startvp != NULL)
+ VN_RELE(startvp);
if (error)
return (set_errno(error));
VN_RELE(vp);
return (0);
}
+
+int
+mkdir(char *dname, int dmode)
+{
+ return (mkdirat(AT_FDCWD, dname, dmode));
+}
diff --git a/usr/src/uts/common/syscall/mknod.c b/usr/src/uts/common/syscall/mknod.c
index 73258f9c2f..82fe837622 100644
--- a/usr/src/uts/common/syscall/mknod.c
+++ b/usr/src/uts/common/syscall/mknod.c
@@ -20,8 +20,7 @@
*/
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -41,11 +40,14 @@
#include <sys/errno.h>
#include <sys/stat.h>
#include <sys/vnode.h>
+#include <sys/file.h>
+#include <sys/fcntl.h>
#include <sys/mode.h>
#include <sys/uio.h>
#include <sys/mkdev.h>
#include <sys/policy.h>
#include <sys/debug.h>
+#include <c2/audit.h>
/*
* Create a special file, a regular file, or a FIFO.
@@ -54,8 +56,9 @@
* dev = device number - b/c specials only
*/
int
-mknod(char *fname, mode_t fmode, dev_t dev)
+mknodat(int fd, char *fname, mode_t fmode, dev_t dev)
{
+ vnode_t *startvp;
vnode_t *vp;
struct vattr vattr;
int error;
@@ -86,10 +89,27 @@ mknod(char *fname, mode_t fmode, dev_t dev)
vattr.va_rdev = dev;
vattr.va_mask |= AT_RDEV;
}
+
+ if (fname == NULL)
+ return (set_errno(EFAULT));
+ if ((error = fgetstartvp(fd, fname, &startvp)) != 0)
+ return (set_errno(error));
+ if (AU_AUDITING() && startvp != NULL)
+ audit_setfsat_path(1);
+
why = ((fmode & S_IFMT) == S_IFDIR) ? CRMKDIR : CRMKNOD;
- if (error = vn_create(fname, UIO_USERSPACE, &vattr, EXCL, 0, &vp,
- why, 0, PTOU(curproc)->u_cmask))
+ error = vn_createat(fname, UIO_USERSPACE, &vattr, EXCL, 0, &vp,
+ why, 0, PTOU(curproc)->u_cmask, startvp);
+ if (startvp != NULL)
+ VN_RELE(startvp);
+ if (error)
return (set_errno(error));
VN_RELE(vp);
return (0);
}
+
+int
+mknod(char *fname, mode_t fmode, dev_t dev)
+{
+ return (mknodat(AT_FDCWD, fname, fmode, dev));
+}
diff --git a/usr/src/uts/common/syscall/open.c b/usr/src/uts/common/syscall/open.c
index 154c1a6953..6559900158 100644
--- a/usr/src/uts/common/syscall/open.c
+++ b/usr/src/uts/common/syscall/open.c
@@ -69,6 +69,18 @@ copen(int startfd, char *fname, int filemode, int createmode)
uint32_t auditing = AU_AUDITING();
char startchar;
+ if (filemode & (FSEARCH|FEXEC)) {
+ /*
+ * Must be one or the other and neither FREAD nor FWRITE
+ * Must not be any of FAPPEND FCREAT FTRUNC FXATTR FXATTRDIROPEN
+ * XXX: Should these just be silently ignored?
+ */
+ if ((filemode & (FREAD|FWRITE)) ||
+ (filemode & (FSEARCH|FEXEC)) == (FSEARCH|FEXEC) ||
+ (filemode & (FAPPEND|FCREAT|FTRUNC|FXATTR|FXATTRDIROPEN)))
+ return (set_errno(EINVAL));
+ }
+
if (startfd == AT_FDCWD) {
/*
* Regular open()
@@ -99,9 +111,8 @@ copen(int startfd, char *fname, int filemode, int createmode)
* Handle __openattrdirat() requests
*/
if (filemode & FXATTRDIROPEN) {
- if (auditing && (startvp != NULL))
+ if (auditing && startvp != NULL)
audit_setfsat_path(1);
-
if (error = lookupnameat(fname, seg, FOLLOW,
NULLVPP, &vp, startvp))
return (set_errno(error));
@@ -188,12 +199,12 @@ copen(int startfd, char *fname, int filemode, int createmode)
}
noxattr:
- if ((filemode & (FREAD|FWRITE|FXATTRDIROPEN)) != 0) {
+ if ((filemode & (FREAD|FWRITE|FSEARCH|FEXEC|FXATTRDIROPEN)) != 0) {
if ((filemode & (FNONBLOCK|FNDELAY)) == (FNONBLOCK|FNDELAY))
filemode &= ~FNDELAY;
error = falloc((vnode_t *)NULL, filemode, &fp, &fd);
if (error == 0) {
- if (auditing && (startvp != NULL))
+ if (auditing && startvp != NULL)
audit_setfsat_path(1);
/*
* Last arg is a don't-care term if
@@ -259,13 +270,13 @@ out:
return (set_errno(error));
}
-#define OPENMODE32(fmode) ((int)((fmode)-FOPEN))
+#define OPENMODE32(fmode) (((fmode) & (FSEARCH | FEXEC))? \
+ (fmode) : (fmode) - FOPEN)
#define OPENMODE64(fmode) (OPENMODE32(fmode) | FOFFMAX)
-#define OPENMODEATTRDIR FXATTRDIROPEN
#ifdef _LP64
#define OPENMODE(fmode) OPENMODE64(fmode)
#else
-#define OPENMODE OPENMODE32
+#define OPENMODE(fmode) OPENMODE32(fmode)
#endif
/*
diff --git a/usr/src/uts/common/syscall/readlink.c b/usr/src/uts/common/syscall/readlink.c
index 4c31e16d3f..e88c842ba7 100644
--- a/usr/src/uts/common/syscall/readlink.c
+++ b/usr/src/uts/common/syscall/readlink.c
@@ -18,9 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -31,8 +31,6 @@
* under license from the Regents of the University of California.
*/
-#pragma ident "%Z%%M% %I% %E% SMI"
-
#include <sys/param.h>
#include <sys/isa_defs.h>
#include <sys/types.h>
@@ -43,16 +41,19 @@
#include <sys/pathname.h>
#include <sys/vnode.h>
#include <sys/file.h>
+#include <sys/fcntl.h>
#include <sys/uio.h>
#include <sys/debug.h>
#include <fs/fs_subr.h>
+#include <c2/audit.h>
/*
* Read the contents of a symbolic link.
*/
ssize_t
-readlink(char *name, char *buf, size_t count)
+readlinkat(int dfd, char *name, char *buf, size_t count)
{
+ vnode_t *startvp;
vnode_t *vp;
struct iovec aiov;
struct uio auio;
@@ -63,12 +64,19 @@ readlink(char *name, char *buf, size_t count)
if ((cnt = (ssize_t)count) < 0)
return (set_errno(EINVAL));
+ if (name == NULL)
+ return (set_errno(EFAULT));
+ if ((error = fgetstartvp(dfd, name, &startvp)) != 0)
+ return (set_errno(error));
lookup:
- if (error = lookupname(name, UIO_USERSPACE, NO_FOLLOW, NULLVPP, &vp)) {
- if ((error == ESTALE) && fs_need_estale_retry(estale_retry++))
+ if (AU_AUDITING() && startvp != NULL)
+ audit_setfsat_path(1);
+ if (error = lookupnameat(name, UIO_USERSPACE, NO_FOLLOW,
+ NULLVPP, &vp, startvp)) {
+ if (error == ESTALE && fs_need_estale_retry(estale_retry++))
goto lookup;
- return (set_errno(error));
+ goto out;
}
if (vp->v_type != VLNK) {
@@ -83,7 +91,8 @@ lookup:
if ((error == ESTALE) &&
fs_need_estale_retry(estale_retry++))
goto lookup;
- return (set_errno(EINVAL));
+ error = EINVAL;
+ goto out;
}
}
aiov.iov_base = buf;
@@ -96,14 +105,22 @@ lookup:
auio.uio_resid = cnt;
error = VOP_READLINK(vp, &auio, CRED(), NULL);
VN_RELE(vp);
- if (error) {
- if ((error == ESTALE) && fs_need_estale_retry(estale_retry++))
- goto lookup;
+ if (error == ESTALE && fs_need_estale_retry(estale_retry++))
+ goto lookup;
+out:
+ if (startvp != NULL)
+ VN_RELE(startvp);
+ if (error)
return (set_errno(error));
- }
return ((ssize_t)(cnt - auio.uio_resid));
}
+ssize_t
+readlink(char *name, char *buf, size_t count)
+{
+ return (readlinkat(AT_FDCWD, name, buf, count));
+}
+
#ifdef _SYSCALL32_IMPL
/*
* readlink32() intentionally returns a ssize_t rather than ssize32_t;
@@ -111,9 +128,16 @@ lookup:
*/
ssize_t
+readlinkat32(int dfd, caddr32_t name, caddr32_t buf, size32_t count)
+{
+ return ((ssize32_t)readlinkat(dfd, (char *)(uintptr_t)name,
+ (char *)(uintptr_t)buf, (ssize32_t)count));
+}
+
+ssize_t
readlink32(caddr32_t name, caddr32_t buf, size32_t count)
{
- return ((ssize32_t)readlink((char *)(uintptr_t)name,
+ return ((ssize32_t)readlinkat(AT_FDCWD, (char *)(uintptr_t)name,
(char *)(uintptr_t)buf, (ssize32_t)count));
}
diff --git a/usr/src/uts/common/syscall/rename.c b/usr/src/uts/common/syscall/rename.c
index 59344790c9..c6e4f08082 100644
--- a/usr/src/uts/common/syscall/rename.c
+++ b/usr/src/uts/common/syscall/rename.c
@@ -42,74 +42,39 @@
#include <sys/debug.h>
#include <sys/file.h>
#include <sys/fcntl.h>
+#include <c2/audit.h>
/*
* Rename a file relative to a given directory
*/
int
-renameat(int fromfd, char *old, int tofd, char *new)
+renameat(int ffd, char *from, int tfd, char *to)
{
- vnode_t *fromvp = NULL;
- vnode_t *tovp = NULL;
- file_t *fp;
+ vnode_t *fstartvp = NULL;
+ vnode_t *tstartvp = NULL;
int error;
- char oldstart;
- char newstart;
- if (copyin(old, &oldstart, sizeof (char)) ||
- copyin(new, &newstart, sizeof (char)))
+ if (from == NULL || to == NULL)
return (set_errno(EFAULT));
+ if ((error = fgetstartvp(ffd, from, &fstartvp)) != 0)
+ goto out;
+ if ((error = fgetstartvp(tfd, to, &tstartvp)) != 0)
+ goto out;
- if (fromfd == AT_FDCWD || tofd == AT_FDCWD) {
- proc_t *p = curproc;
+ error = vn_renameat(fstartvp, from, tstartvp, to, UIO_USERSPACE);
- mutex_enter(&p->p_lock);
- if (fromfd == AT_FDCWD) {
- fromvp = PTOU(p)->u_cdir;
- VN_HOLD(fromvp);
- }
- if (tofd == AT_FDCWD) {
- tovp = PTOU(p)->u_cdir;
- VN_HOLD(tovp);
- }
- mutex_exit(&p->p_lock);
- }
-
- if (fromvp == NULL && oldstart != '/') {
- if ((fp = getf(fromfd)) == NULL) {
- if (tovp != NULL)
- VN_RELE(tovp);
- return (set_errno(EBADF));
- }
- fromvp = fp->f_vnode;
- VN_HOLD(fromvp);
- releasef(fromfd);
- }
-
- if (tovp == NULL && newstart != '/') {
- if ((fp = getf(tofd)) == NULL) {
- if (fromvp != NULL)
- VN_RELE(fromvp);
- return (set_errno(EBADF));
- }
- tovp = fp->f_vnode;
- VN_HOLD(tovp);
- releasef(tofd);
- }
-
- error = vn_renameat(fromvp, old, tovp, new, UIO_USERSPACE);
-
- if (fromvp != NULL)
- VN_RELE(fromvp);
- if (tovp != NULL)
- VN_RELE(tovp);
+out:
+ if (fstartvp != NULL)
+ VN_RELE(fstartvp);
+ if (tstartvp != NULL)
+ VN_RELE(tstartvp);
if (error)
return (set_errno(error));
return (0);
}
int
-rename(char *old, char *new)
+rename(char *from, char *to)
{
- return (renameat(AT_FDCWD, old, AT_FDCWD, new));
+ return (renameat(AT_FDCWD, from, AT_FDCWD, to));
}
diff --git a/usr/src/uts/common/syscall/stat.c b/usr/src/uts/common/syscall/stat.c
index d636b1c720..4085104cc7 100644
--- a/usr/src/uts/common/syscall/stat.c
+++ b/usr/src/uts/common/syscall/stat.c
@@ -102,7 +102,7 @@ cstatat_getvp(int fd, char *name, int follow, vnode_t **vp, cred_t **cred)
}
*cred = cr;
- if (AU_AUDITING() && (startvp != NULL))
+ if (AU_AUDITING() && startvp != NULL)
audit_setfsat_path(1);
lookup:
diff --git a/usr/src/uts/common/syscall/symlink.c b/usr/src/uts/common/syscall/symlink.c
index 99dcdf01a4..87fa7bee60 100644
--- a/usr/src/uts/common/syscall/symlink.c
+++ b/usr/src/uts/common/syscall/symlink.c
@@ -18,9 +18,9 @@
*
* CDDL HEADER END
*/
+
/*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
+ * Copyright (c) 1994, 2010, Oracle and/or its affiliates. All rights reserved.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
@@ -40,6 +40,8 @@
#include <sys/pathname.h>
#include <sys/vfs.h>
#include <sys/vnode.h>
+#include <sys/file.h>
+#include <sys/fcntl.h>
#include <sys/proc.h>
#include <sys/uio.h>
#include <sys/debug.h>
@@ -51,8 +53,9 @@
* name is passed as string argument, not converted to vnode reference.
*/
int
-symlink(char *target, char *linkname)
+symlinkat(char *target, int dfd, char *linkname)
{
+ vnode_t *startvp;
vnode_t *dvp;
struct vattr vattr;
struct pathname lpn;
@@ -60,15 +63,23 @@ symlink(char *target, char *linkname)
size_t tlen;
int error;
int estale_retry = 0;
+ int auditing = AU_AUDITING();
+
+ if (linkname == NULL)
+ return (set_errno(EFAULT));
+ if ((error = fgetstartvp(dfd, linkname, &startvp)) != 0)
+ return (set_errno(error));
top:
if (error = pn_get(linkname, UIO_USERSPACE, &lpn))
- return (set_errno(error));
- if (error = lookuppn(&lpn, NULL, NO_FOLLOW, &dvp, NULLVPP)) {
+ goto out;
+ if (auditing && startvp != NULL)
+ audit_setfsat_path(2);
+ if (error = lookuppnat(&lpn, NULL, NO_FOLLOW, &dvp, NULLVPP, startvp)) {
pn_free(&lpn);
- if ((error == ESTALE) && fs_need_estale_retry(estale_retry++))
+ if (error == ESTALE && fs_need_estale_retry(estale_retry++))
goto top;
- return (set_errno(error));
+ goto out;
}
if (vn_is_readonly(dvp))
error = EROFS;
@@ -82,7 +93,7 @@ top:
vattr.va_mask = AT_TYPE|AT_MODE;
error = VOP_SYMLINK(dvp, lpn.pn_path, &vattr,
tbuf, CRED(), NULL, 0);
- if (AU_AUDITING())
+ if (auditing)
audit_symlink_create(dvp, lpn.pn_path,
tbuf, error);
}
@@ -90,10 +101,18 @@ top:
}
pn_free(&lpn);
VN_RELE(dvp);
- if (error) {
- if ((error == ESTALE) && fs_need_estale_retry(estale_retry++))
- goto top;
+ if (error == ESTALE && fs_need_estale_retry(estale_retry++))
+ goto top;
+out:
+ if (startvp != NULL)
+ VN_RELE(startvp);
+ if (error)
return (set_errno(error));
- }
return (0);
}
+
+int
+symlink(char *target, char *linkname)
+{
+ return (symlinkat(target, AT_FDCWD, linkname));
+}
diff --git a/usr/src/uts/common/syscall/unlink.c b/usr/src/uts/common/syscall/unlink.c
index 8ee0b9ff0d..8f48ad0d15 100644
--- a/usr/src/uts/common/syscall/unlink.c
+++ b/usr/src/uts/common/syscall/unlink.c
@@ -50,44 +50,21 @@
int
unlinkat(int fd, char *name, int flags)
{
- file_t *dirfp;
- vnode_t *dirvp;
+ vnode_t *startvp;
int error;
- char startchar;
- if (fd == AT_FDCWD && name == NULL)
+ if (name == NULL)
return (set_errno(EFAULT));
-
- if (name != NULL) {
- if (copyin(name, &startchar, sizeof (char)))
- return (set_errno(EFAULT));
- } else
- startchar = '\0';
-
- if (fd == AT_FDCWD) {
- dirvp = NULL;
- } else {
- if (startchar != '/') {
- if ((dirfp = getf(fd)) == NULL) {
- return (set_errno(EBADF));
- }
- dirvp = dirfp->f_vnode;
- VN_HOLD(dirvp);
- releasef(fd);
- } else {
- dirvp = NULL;
- }
- }
-
- if (AU_AUDITING() && (dirvp != NULL))
+ if ((error = fgetstartvp(fd, name, &startvp)) != 0)
+ return (set_errno(error));
+ if (AU_AUDITING() && startvp != NULL)
audit_setfsat_path(1);
- error = vn_removeat(dirvp, name,
- UIO_USERSPACE, (flags == AT_REMOVEDIR) ? RMDIRECTORY : RMFILE);
- if (dirvp != NULL)
- VN_RELE(dirvp);
-
- if (error != NULL)
+ error = vn_removeat(startvp, name, UIO_USERSPACE,
+ (flags == AT_REMOVEDIR) ? RMDIRECTORY : RMFILE);
+ if (startvp != NULL)
+ VN_RELE(startvp);
+ if (error)
return (set_errno(error));
return (0);
}
diff --git a/usr/src/uts/common/syscall/utime.c b/usr/src/uts/common/syscall/utime.c
index 19ce7bb972..36eddc90d2 100644
--- a/usr/src/uts/common/syscall/utime.c
+++ b/usr/src/uts/common/syscall/utime.c
@@ -83,10 +83,9 @@ cfutimesat(int fd, char *fname, int nmflag, vattr_t *vap, int flags, int follow)
}
}
- if (AU_AUDITING() && (startvp != NULL))
- audit_setfsat_path(1);
-
if ((nmflag == 1) || ((nmflag == 2) && (fname != NULL))) {
+ if (AU_AUDITING() && startvp != NULL)
+ audit_setfsat_path(1);
if ((error = lookupnameat(fname, UIO_USERSPACE,
follow, NULLVPP, &vp, startvp)) != 0) {
if (startvp != NULL)