diff options
author | Roger A. Faulkner <Roger.Faulkner@Oracle.COM> | 2010-07-07 17:36:17 -0700 |
---|---|---|
committer | Roger A. Faulkner <Roger.Faulkner@Oracle.COM> | 2010-07-07 17:36:17 -0700 |
commit | 794f0adb050e571bbfde4d2a19b9f88b852079dd (patch) | |
tree | c1735b3eda175e9096f5b062a73614e73aa5cd9a /usr/src/uts/common | |
parent | 07925104db56e5c3eacc4865b918bd16af5cec59 (diff) | |
download | illumos-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')
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) |