Index: contrib/openbsm/etc/audit_event =================================================================== --- contrib/openbsm/etc/audit_event +++ contrib/openbsm/etc/audit_event @@ -601,6 +601,19 @@ 43238:AUE_SETLOGINCLASS:setloginclass(2):pc 43239:AUE_POSIX_FADVISE:posix_fadvise(2):no 43240:AUE_SCTP_GENERIC_SENDMSG_IOV:sctp_generic_sendmsg_iov(2):nt +43241:AUE_ABORT2:abort(2):pc +43242:AUE_SEMTIMEDWAIT:sem_timedwait(3):ip +43243:AUE_SEMDESTROY:sem_destroy(3):ip +43244:AUE_SEMGETVALUE:sem_getvalue(3):ip +43245:AUE_SEMINIT:sem_init(3):ip +43246:AUE_SEMPOST:sem_post(3):ip +43247:AUE_SEMTRYWAIT:sem_trywait(3):ip +43258:AUE_SEMWAIT:sem_wait(3):ip +43259:AUE_FGETUUID:fgetuuid(2):ip +43260:AUE_GETUUID:getuuid(2):ip +43261:AUE_LGETUUID:lgetuuid(2):ip +43262:AUE_EXECVEAT:execveat(2):pc,ex +43263:AUE_SHMRENAME:shm_rename(2):ip # # Solaris userspace events. # Index: contrib/openbsm/sys/bsm/audit_kevents.h =================================================================== --- contrib/openbsm/sys/bsm/audit_kevents.h +++ contrib/openbsm/sys/bsm/audit_kevents.h @@ -640,6 +640,19 @@ #define AUE_SETLOGINCLASS 43238 /* FreeBSD-specific. */ #define AUE_POSIX_FADVISE 43239 /* FreeBSD-specific. */ #define AUE_SCTP_GENERIC_SENDMSG_IOV 43240 /* FreeBSD-specific. */ +#define AUE_ABORT2 43241 /* FreeBSD-specific. */ +#define AUE_SEMTIMEDWAIT 43242 /* FreeBSD-specific. */ +#define AUE_SEMDESTROY 43243 /* FreeBSD-specific. */ +#define AUE_SEMGETVALUE 43244 /* FreeBSD-specific. */ +#define AUE_SEMINIT 43245 /* FreeBSD-specific. */ +#define AUE_SEMPOST 43246 /* FreeBSD-specific. */ +#define AUE_SEMTRYWAIT 43247 /* FreeBSD-specific. */ +#define AUE_SEMWAIT 43258 /* FreeBSD-specific. */ +#define AUE_FGETUUID 43259 /* CADETS. */ +#define AUE_GETUUID 43260 /* CADETS. */ +#define AUE_LGETUUID 43261 /* CADETS. */ +#define AUE_EXECVEAT 43262 /* FreeBSD/Linux. */ +#define AUE_SHMRENAME 43263 /* FreeBSD-specific. */ /* * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the @@ -794,12 +807,6 @@ #define AUE_REMOVEXATTR AUE_NULL #define AUE_SBRK AUE_NULL #define AUE_SELECT AUE_NULL -#define AUE_SEMDESTROY AUE_NULL -#define AUE_SEMGETVALUE AUE_NULL -#define AUE_SEMINIT AUE_NULL -#define AUE_SEMPOST AUE_NULL -#define AUE_SEMTRYWAIT AUE_NULL -#define AUE_SEMWAIT AUE_NULL #define AUE_SEMWAITSIGNAL AUE_NULL #define AUE_SETITIMER AUE_NULL #define AUE_SETSGROUPS AUE_NULL Index: sys/bsm/audit_kevents.h =================================================================== --- sys/bsm/audit_kevents.h +++ sys/bsm/audit_kevents.h @@ -644,6 +644,19 @@ #define AUE_SETLOGINCLASS 43238 /* FreeBSD-specific. */ #define AUE_POSIX_FADVISE 43239 /* FreeBSD-specific. */ #define AUE_SCTP_GENERIC_SENDMSG_IOV 43240 /* FreeBSD-specific. */ +#define AUE_ABORT2 43241 /* FreeBSD-specific. */ +#define AUE_SEMTIMEDWAIT 43242 /* FreeBSD-specific. */ +#define AUE_SEMDESTROY 43243 /* FreeBSD-specific. */ +#define AUE_SEMGETVALUE 43244 /* FreeBSD-specific. */ +#define AUE_SEMINIT 43245 /* FreeBSD-specific. */ +#define AUE_SEMPOST 43246 /* FreeBSD-specific. */ +#define AUE_SEMTRYWAIT 43247 /* FreeBSD-specific. */ +#define AUE_SEMWAIT 43258 /* FreeBSD-specific. */ +#define AUE_FGETUUID 43259 /* CADETS. */ +#define AUE_GETUUID 43260 /* CADETS. */ +#define AUE_LGETUUID 43261 /* CADETS. */ +#define AUE_EXECVEAT 43262 /* FreeBSD/Linux. */ +#define AUE_SHMRENAME 43263 /* FreeBSD-specific. */ /* * Darwin BSM uses a number of AUE_O_* definitions, which are aliased to the @@ -798,12 +811,6 @@ #define AUE_REMOVEXATTR AUE_NULL #define AUE_SBRK AUE_NULL #define AUE_SELECT AUE_NULL -#define AUE_SEMDESTROY AUE_NULL -#define AUE_SEMGETVALUE AUE_NULL -#define AUE_SEMINIT AUE_NULL -#define AUE_SEMPOST AUE_NULL -#define AUE_SEMTRYWAIT AUE_NULL -#define AUE_SEMWAIT AUE_NULL #define AUE_SEMWAITSIGNAL AUE_NULL #define AUE_SETITIMER AUE_NULL #define AUE_SETSGROUPS AUE_NULL Index: sys/compat/freebsd32/freebsd32_sysent.c =================================================================== --- sys/compat/freebsd32/freebsd32_sysent.c +++ sys/compat/freebsd32/freebsd32_sysent.c @@ -661,5 +661,5 @@ { AS(copy_file_range_args), (sy_call_t *)sys_copy_file_range, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 569 = copy_file_range */ { AS(freebsd32___sysctlbyname_args), (sy_call_t *)freebsd32___sysctlbyname, AUE_SYSCTL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 570 = freebsd32___sysctlbyname */ { AS(shm_open2_args), (sy_call_t *)sys_shm_open2, AUE_SHMOPEN, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 571 = shm_open2 */ - { AS(shm_rename_args), (sy_call_t *)sys_shm_rename, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 572 = shm_rename */ + { AS(shm_rename_args), (sy_call_t *)sys_shm_rename, AUE_SHMRENAME, NULL, 0, 0, 0, SY_THR_STATIC }, /* 572 = shm_rename */ }; Index: sys/compat/freebsd32/syscalls.master =================================================================== --- sys/compat/freebsd32/syscalls.master +++ sys/compat/freebsd32/syscalls.master @@ -1157,7 +1157,7 @@ 571 AUE_SHMOPEN NOPROTO { int shm_open2( \ const char *path, int flags, mode_t mode, \ int shmflags, const char *name); } -572 AUE_NULL NOPROTO { int shm_rename(const char *path_from, \ +572 AUE_SHMRENAME NOPROTO { int shm_rename(const char *path_from, \ const char *path_to, int flags); } ; vim: syntax=off Index: sys/kern/init_sysent.c =================================================================== --- sys/kern/init_sysent.c +++ sys/kern/init_sysent.c @@ -627,5 +627,5 @@ { AS(copy_file_range_args), (sy_call_t *)sys_copy_file_range, AUE_NULL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 569 = copy_file_range */ { AS(__sysctlbyname_args), (sy_call_t *)sys___sysctlbyname, AUE_SYSCTL, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 570 = __sysctlbyname */ { AS(shm_open2_args), (sy_call_t *)sys_shm_open2, AUE_SHMOPEN, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 571 = shm_open2 */ - { AS(shm_rename_args), (sy_call_t *)sys_shm_rename, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 572 = shm_rename */ + { AS(shm_rename_args), (sy_call_t *)sys_shm_rename, AUE_SHMRENAME, NULL, 0, 0, 0, SY_THR_STATIC }, /* 572 = shm_rename */ }; Index: sys/kern/syscalls.master =================================================================== --- sys/kern/syscalls.master +++ sys/kern/syscalls.master @@ -3205,7 +3205,7 @@ _In_z_ const char *name ); } -572 AUE_NULL STD { +572 AUE_SHMRENAME STD { int shm_rename( _In_z_ const char *path_from, _In_z_ const char *path_to, Index: sys/kern/uipc_shm.c =================================================================== --- sys/kern/uipc_shm.c +++ sys/kern/uipc_shm.c @@ -122,6 +122,8 @@ static int shm_remove(char *path, Fnv32_t fnv, struct ucred *ucred); static int shm_dotruncate_locked(struct shmfd *shmfd, off_t length, void *rl_cookie); +static int shm_copyin_path(struct thread *td, const char *userpath_in, + char **path_out); static fo_rdwr_t shm_read; static fo_rdwr_t shm_write; @@ -422,6 +424,46 @@ } static int +shm_copyin_path(struct thread *td, const char *userpath_in, char **path_out) { + int error; + char *path; + const char *pr_path; + size_t pr_pathlen; + + error = 0; + + path = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK); + pr_path = td->td_ucred->cr_prison->pr_path; + + /* Construct a full pathname for jailed callers. */ + pr_pathlen = strcmp(pr_path, "/") == 0 ? 0 + : strlcpy(path, pr_path, MAXPATHLEN); + error = copyinstr(userpath_in, path + pr_pathlen, + MAXPATHLEN - pr_pathlen, NULL); + if (error != 0) + goto out; + +#ifdef KTRACE + if (KTRPOINT(curthread, KTR_NAMEI)) + ktrnamei(path); +#endif + + /* Require paths to start with a '/' character. */ + if (path[pr_pathlen] != '/') { + error = EINVAL; + goto out; + } + + *path_out = path; + +out: + if (error != 0) + free(path, M_SHMFD); + + return (error); +} + +static int shm_dotruncate_locked(struct shmfd *shmfd, off_t length, void *rl_cookie) { vm_object_t object; @@ -708,9 +750,7 @@ struct shmfd *shmfd; struct file *fp; char *path; - const char *pr_path; void *rl_cookie; - size_t pr_pathlen; Fnv32_t fnv; mode_t cmode; int fd, error; @@ -768,25 +808,10 @@ shmfd = shm_alloc(td->td_ucred, cmode); shmfd->shm_seals = initial_seals; } else { - path = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK); - pr_path = td->td_ucred->cr_prison->pr_path; - - /* Construct a full pathname for jailed callers. */ - pr_pathlen = strcmp(pr_path, "/") == 0 ? 0 - : strlcpy(path, pr_path, MAXPATHLEN); - error = copyinstr(userpath, path + pr_pathlen, - MAXPATHLEN - pr_pathlen, NULL); -#ifdef KTRACE - if (error == 0 && KTRPOINT(curthread, KTR_NAMEI)) - ktrnamei(path); -#endif - /* Require paths to start with a '/' character. */ - if (error == 0 && path[pr_pathlen] != '/') - error = EINVAL; + error = shm_copyin_path(td, userpath, &path); if (error) { fdclose(td, fp, fd); fdrop(fp, td); - free(path, M_SHMFD); return (error); } @@ -919,25 +944,13 @@ sys_shm_unlink(struct thread *td, struct shm_unlink_args *uap) { char *path; - const char *pr_path; - size_t pr_pathlen; Fnv32_t fnv; int error; - path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK); - pr_path = td->td_ucred->cr_prison->pr_path; - pr_pathlen = strcmp(pr_path, "/") == 0 ? 0 - : strlcpy(path, pr_path, MAXPATHLEN); - error = copyinstr(uap->path, path + pr_pathlen, MAXPATHLEN - pr_pathlen, - NULL); - if (error) { - free(path, M_TEMP); + error = shm_copyin_path(td, uap->path, &path); + if (error) return (error); - } -#ifdef KTRACE - if (KTRPOINT(curthread, KTR_NAMEI)) - ktrnamei(path); -#endif + AUDIT_ARG_UPATH1_CANON(path); fnv = fnv_32_str(path, FNV1_32_INIT); sx_xlock(&shm_dict_lock); @@ -959,6 +972,7 @@ int flags; flags = uap->flags; + AUDIT_ARG_FFLAGS(flags); /* * Make sure the user passed only valid flags. @@ -982,20 +996,29 @@ goto out; } +#ifdef CAPABILITY_MODE /* - * Malloc zone M_SHMFD, since this path may end up freed later from - * M_SHMFD if we end up doing an insert. + * Let's restrict use in capability mode. Let's allow only SHM_ANON uses + * in capability mode, to parallel shm_open. Since we have a later check + * for to == from, and is a no-op, then this becomes simply a bail out. */ - path_from = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK); - error = copyinstr(uap->path_from, path_from, MAXPATHLEN, NULL); - if (error) + if (IN_CAPABILITY_MODE(td)) { + error = ECAPMODE; + goto out; + } +#endif + + error = shm_copyin_path(td, uap->path_from, &path_from); + if (error != 0) goto out; - path_to = malloc(MAXPATHLEN, M_SHMFD, M_WAITOK); - error = copyinstr(uap->path_to, path_to, MAXPATHLEN, NULL); - if (error) + error = shm_copyin_path(td, uap->path_to, &path_to); + if (error != 0) goto out; + AUDIT_ARG_UPATH1_CANON(path_from); + AUDIT_ARG_UPATH2_CANON(path_to); + /* Rename with from/to equal is a no-op */ if (strncmp(path_from, path_to, MAXPATHLEN) == 0) goto out; @@ -1007,16 +1030,14 @@ fd_from = shm_lookup(path_from, fnv_from); if (fd_from == NULL) { - sx_xunlock(&shm_dict_lock); error = ENOENT; - goto out; + goto out_locked; } fd_to = shm_lookup(path_to, fnv_to); if ((flags & SHM_RENAME_NOREPLACE) != 0 && fd_to != NULL) { - sx_xunlock(&shm_dict_lock); error = EEXIST; - goto out; + goto out_locked; } /* @@ -1032,10 +1053,9 @@ */ KASSERT(error != ENOENT, ("Our shm disappeared during shm_rename: %s", path_from)); - if (error) { + if (error != 0) { shm_drop(fd_from); - sx_xunlock(&shm_dict_lock); - goto out; + goto out_locked; } /* @@ -1058,13 +1078,12 @@ * operation. */ error = shm_remove(path_to, fnv_to, td->td_ucred); - if (error && error != ENOENT) { + if (error != 0 && error != ENOENT) { shm_insert(path_from, fnv_from, fd_from); shm_drop(fd_from); /* Don't free path_from now, since the hash references it */ path_from = NULL; - sx_xunlock(&shm_dict_lock); - goto out; + goto out_locked; } shm_insert(path_to, fnv_to, fd_from); @@ -1074,22 +1093,20 @@ /* We kept a ref when we removed, and incremented again in insert */ shm_drop(fd_from); -#ifdef DEBUG KASSERT(fd_from->shm_refs > 0, ("Expected >0 refs; got: %d\n", fd_from->shm_refs)); -#endif if ((flags & SHM_RENAME_EXCHANGE) != 0 && fd_to != NULL) { shm_insert(path_from, fnv_from, fd_to); path_from = NULL; shm_drop(fd_to); -#ifdef DEBUG KASSERT(fd_to->shm_refs > 0, ("Expected >0 refs; got: %d\n", fd_to->shm_refs)); -#endif } error = 0; + +out_locked: sx_xunlock(&shm_dict_lock); out: @@ -1097,7 +1114,7 @@ free(path_from, M_SHMFD); if (path_to != NULL) free(path_to, M_SHMFD); - return(error); + return (error); } int Index: sys/security/audit/audit_bsm.c =================================================================== --- sys/security/audit/audit_bsm.c +++ sys/security/audit/audit_bsm.c @@ -1565,6 +1565,16 @@ } break; + /* shm_rename is a non-Posix extension to the Posix shm implementation */ + case AUE_SHMRENAME: + UPATH1_TOKENS; + UPATH2_TOKENS; + if (ARG_IS_VALID(kar, ARG_FFLAGS)) { + tok = au_to_arg32(2, "flags", ar->ar_arg_fflags); + kau_write(rec, tok); + } + break; + /* AUE_SHMOPEN, AUE_SHMUNLINK, AUE_SEMOPEN, AUE_SEMCLOSE * and AUE_SEMUNLINK are Posix IPC */ case AUE_SHMOPEN: Index: sys/sys/mman.h =================================================================== --- sys/sys/mman.h +++ sys/sys/mman.h @@ -321,11 +321,11 @@ int mlockall(int); int munlockall(void); int shm_open(const char *, int, mode_t); -int shm_rename(const char *, const char *, int); int shm_unlink(const char *); #endif #if __BSD_VISIBLE int memfd_create(const char *, unsigned int); +int shm_rename(const char *, const char *, int); #endif __END_DECLS Index: sys/sys/sysproto.h =================================================================== --- sys/sys/sysproto.h +++ sys/sys/sysproto.h @@ -3129,7 +3129,7 @@ #define SYS_AUE_copy_file_range AUE_NULL #define SYS_AUE___sysctlbyname AUE_SYSCTL #define SYS_AUE_shm_open2 AUE_SHMOPEN -#define SYS_AUE_shm_rename AUE_NULL +#define SYS_AUE_shm_rename AUE_SHMRENAME #undef PAD_ #undef PADL_ Index: tests/sys/posixshm/posixshm_test.c =================================================================== --- tests/sys/posixshm/posixshm_test.c +++ tests/sys/posixshm/posixshm_test.c @@ -53,7 +53,7 @@ static void gen_a_test_path(char *path) { - snprintf(path, TEST_PATH_LEN, "%s/tmp.XXXXXX%d", + snprintf(path, TEST_PATH_LEN, "/%s/tmp.XXXXXX%d", getenv("TMPDIR") == NULL ? "/tmp" : getenv("TMPDIR"), test_path_idx); @@ -232,12 +232,14 @@ int rc; gen_test_path(); + gen_test_path2(); rc = shm_rename(test_path, test_path2, 0); if (rc != -1) atf_tc_fail("shm_rename of nonexisting shm succeeded unexpectedly"); if (errno != ENOENT) - atf_tc_fail("Expected ENOENT to rename of nonexistent shm"); + atf_tc_fail("Expected ENOENT to rename of nonexistent shm; got %d", + errno); } ATF_TC_WITHOUT_HEAD(rename_to_anon);