diff options
author | rwatson <rwatson@FreeBSD.org> | 2006-12-16 11:30:54 +0000 |
---|---|---|
committer | rwatson <rwatson@FreeBSD.org> | 2006-12-16 11:30:54 +0000 |
commit | 4d1fe0d4258ab77e3ac80848b6209a996f1f3c57 (patch) | |
tree | 449da2a473388d25f5b3f180f8b7daea92cbf338 | |
parent | 38887bc05dfc35770cb63b5b74433a3da62f4c62 (diff) | |
download | FreeBSD-src-4d1fe0d4258ab77e3ac80848b6209a996f1f3c57.zip FreeBSD-src-4d1fe0d4258ab77e3ac80848b6209a996f1f3c57.tar.gz |
For now, back out sysv_ipc.c:1.30, which caused shmget() with odd mode
arguments to fail. The mode field for shmget() appears to have undefined
meaning in the context of an already-present IPC object, but applications
appear to assume any arbitrary passed value will be ignored. I had hoped
to revisit this more quickly, but am removing the change for now to
prevent toe-stubbing.
Reported by: JAroslav Suchanek <jarda at grisoft dot cz>
PR: kern/106078
-rw-r--r-- | sys/kern/sysv_ipc.c | 104 |
1 files changed, 38 insertions, 66 deletions
diff --git a/sys/kern/sysv_ipc.c b/sys/kern/sysv_ipc.c index 0cbb4bb..8fec1da 100644 --- a/sys/kern/sysv_ipc.c +++ b/sys/kern/sysv_ipc.c @@ -1,12 +1,8 @@ /* $NetBSD: sysv_ipc.c,v 1.7 1994/06/29 06:33:11 cgd Exp $ */ /*- * Copyright (c) 1994 Herb Peyerl <hpeyerl@novatel.ca> - * Copyright (c) 2006 nCircle Network Security, Inc. * All rights reserved. * - * This software was developed by Robert N. M. Watson for the TrustedBSD - * Project under contract to nCircle Network Security, Inc. - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -43,7 +39,6 @@ __FBSDID("$FreeBSD$"); #include <sys/sem.h> #include <sys/shm.h> #include <sys/ipc.h> -#include <sys/priv.h> #include <sys/proc.h> #include <sys/ucred.h> @@ -77,73 +72,50 @@ shmexit(struct vmspace *vm) * Note: The MAC Framework does not require any modifications to the * ipcperm() function, as access control checks are performed throughout the * implementation of each primitive. Those entry point calls complement the - * ipcperm() discertionary checks. Unlike file system discretionary access - * control, the original create of an object is given the same rights as the - * current owner. + * ipcperm() discertionary checks. */ int -ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode) +ipcperm(td, perm, mode) + struct thread *td; + struct ipc_perm *perm; + int mode; { struct ucred *cred = td->td_ucred; - int error, obj_mode, dac_granted, priv_granted; - - dac_granted = 0; - if (cred->cr_uid == perm->cuid || cred->cr_uid == perm->uid) { - obj_mode = perm->mode; - dac_granted |= IPC_M; - } else if (groupmember(perm->gid, cred) || - groupmember(perm->cgid, cred)) { - obj_mode = perm->mode; - obj_mode <<= 3; + int error; + + if (cred->cr_uid != perm->cuid && cred->cr_uid != perm->uid) { + /* + * For a non-create/owner, we require privilege to + * modify the object protections. Note: some other + * implementations permit IPC_M to be delegated to + * unprivileged non-creator/owner uids/gids. + */ + if (mode & IPC_M) { + error = suser(td); + if (error) + return (error); + } + /* + * Try to match against creator/owner group; if not, fall + * back on other. + */ + mode >>= 3; + if (!groupmember(perm->gid, cred) && + !groupmember(perm->cgid, cred)) + mode >>= 3; } else { - obj_mode = perm->mode; - obj_mode <<= 6; + /* + * Always permit the creator/owner to update the object + * protections regardless of whether the object mode + * permits it. + */ + if (mode & IPC_M) + return (0); } - /* - * While the System V IPC permission model allows IPC_M to be - * granted, as part of the mode, our implementation requires - * privilege to adminster the object if not the owner or creator. - */ -#if 0 - if (obj_mode & IPC_M) - dac_granted |= IPC_M; -#endif - if (obj_mode & IPC_R) - dac_granted |= IPC_R; - if (obj_mode & IPC_W) - dac_granted |= IPC_W; - - /* - * Simple case: all required rights are granted by DAC. - */ - if ((dac_granted & acc_mode) == acc_mode) - return (0); - - /* - * Privilege is required to satisfy the request. - */ - priv_granted = 0; - if ((acc_mode & IPC_M) && !(dac_granted & IPC_M)) { - error = priv_check(td, PRIV_IPC_ADMIN); - if (error == 0) - priv_granted |= IPC_M; + if ((mode & perm->mode) != mode) { + if (suser(td) != 0) + return (EACCES); } - - if ((acc_mode & IPC_R) && !(dac_granted & IPC_R)) { - error = priv_check(td, PRIV_IPC_READ); - if (error == 0) - priv_granted |= IPC_R; - } - - if ((acc_mode & IPC_W) && !(dac_granted & IPC_W)) { - error = priv_check(td, PRIV_IPC_WRITE); - if (error == 0) - priv_granted |= IPC_W; - } - - if (((dac_granted | priv_granted) & acc_mode) == acc_mode) - return (0); - else - return (EACCES); + return (0); } |