Date: Thu, 28 Sep 2006 19:38:18 GMT From: Robert Watson <rwatson@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 106842 for review Message-ID: <200609281938.k8SJcI2G038387@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=106842 Change 106842 by rwatson@rwatson_zoo on 2006/09/28 19:38:05 First cut at revised ipcperm(). Untested. Affected files ... .. //depot/projects/trustedbsd/priv/sys/kern/sysv_ipc.c#2 edit Differences ... ==== //depot/projects/trustedbsd/priv/sys/kern/sysv_ipc.c#2 (text+ko) ==== @@ -1,6 +1,7 @@ /* $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 Robert N. M. Watson * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -39,6 +40,7 @@ #include <sys/sem.h> #include <sys/shm.h> #include <sys/ipc.h> +#include <sys/priv.h> #include <sys/proc.h> #include <sys/ucred.h> @@ -72,50 +74,73 @@ * 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. + * ipcperm() discertionary checks. Unlike file system discretionary access + * control, the original create of an object is given the same rights as the + * current owner. */ int -ipcperm(td, perm, mode) - struct thread *td; - struct ipc_perm *perm; - int mode; +ipcperm(struct thread *td, struct ipc_perm *perm, int acc_mode) { struct ucred *cred = td->td_ucred; - int error; + int error, obj_mode, dac_granted, priv_granted; - 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; + 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; } else { - /* - * Always permit the creator/owner to update the object - * protections regardless of whether the object mode - * permits it. - */ - if (mode & IPC_M) - return (0); + obj_mode = perm->mode; + obj_mode <<= 6; + } + + /* + * 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 ((acc_mode & IPC_R) && !(dac_granted & IPC_R)) { + error = priv_check(td, PRIV_IPC_READ); + if (error == 0) + priv_granted |= IPC_R; } - if ((mode & perm->mode) != mode) { - if (suser(td) != 0) - return (EACCES); + if ((acc_mode & IPC_W) && !(dac_granted & IPC_W)) { + error = priv_check(td, PRIV_IPC_WRITE); + if (error == 0) + priv_granted |= IPC_W; } - return (0); + + if (((dac_granted | priv_granted) & acc_mode) == acc_mode) + return (0); + else + return (EACCES); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200609281938.k8SJcI2G038387>