[PATCH 0/4] MultiAdmin 1.0.7 - Kernel

This is a discussion on [PATCH 0/4] MultiAdmin 1.0.7 - Kernel ; As per James's request, I am reposting the MultiAdmin LSM in its current form (2.6.23.1, still with the modular LSM interface). - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org ...

+ Reply to Thread
Results 1 to 7 of 7

Thread: [PATCH 0/4] MultiAdmin 1.0.7

  1. [PATCH 0/4] MultiAdmin 1.0.7


    As per James's request, I am reposting the MultiAdmin LSM in its
    current form (2.6.23.1, still with the modular LSM interface).
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  2. [PATCH 4/4] MultiAdmin 1.0.7


    [PATCH 4/4] MultiAdmin module

    - Add the MultiAdmin to the mainline tree.
    I hope the rest is self-explanatory

    Signed-off-by: Jan Engelhardt , May 01 2006
    Modified July 11 2006

    ---
    security/Kconfig | 17 +
    security/Makefile | 3
    security/multiadm.c | 628 ++++++++++++++++++++++++++++++++++++++++++++++++++ ++
    3 files changed, 648 insertions(+)

    Index: linux-2.6.23.1/security/Kconfig
    ================================================== =================
    --- linux-2.6.23.1.orig/security/Kconfig
    +++ linux-2.6.23.1/security/Kconfig
    @@ -81,6 +81,23 @@ config SECURITY_NETWORK_XFRM
    IPSec.
    If you are unsure how to answer this question, answer N.

    +config SECURITY_MULTIADM
    + tristate "MultiAdmin security module"
    + depends on SECURITY
    + select SECURITY_CAPABILITIES
    + ---help---
    + The MultiAdmin security kernel module provides means to have multiple
    + "root" users with unique UIDs. This fixes collation order problems
    + which for example appear with NSCD, allows to have files with
    + determinable owner and allows to track the quota usage for every
    + user, since they now have a unique uid.
    +
    + It also implements a "sub-admin", a partially restricted root user
    + (or enhanced normal user, depending on the way you see it), who has
    + full read-only access to most subsystems, and additional write rights
    + only to a limited subset, e.g. writing to files or killing processes
    + only of certain users.
    +
    config SECURITY_CAPABILITIES
    tristate "Default Linux Capabilities"
    depends on SECURITY
    Index: linux-2.6.23.1/security/Makefile
    ================================================== =================
    --- linux-2.6.23.1.orig/security/Makefile
    +++ linux-2.6.23.1/security/Makefile
    @@ -2,6 +2,9 @@
    # Makefile for the kernel security code
    #

    +obj-$(CONFIG_SECURITY_MULTIADM) += multiadm.o
    +CFLAGS_multiadm.o += $(if $(wildcard security/apparmor),-DAPPARMOR,)
    +
    obj-$(CONFIG_KEYS) += keys/
    subdir-$(CONFIG_SECURITY_SELINUX) += selinux

    Index: linux-2.6.23.1/security/multiadm.c
    ================================================== =================
    --- /dev/null
    +++ linux-2.6.23.1/security/multiadm.c
    @@ -0,0 +1,628 @@
    +/*
    + * MultiAdmin Security Module
    + * Copyright © Jan Engelhardt , 2005 - 2007
    + * v1.0.7, July 2007
    + *
    + * This program is free software; you can redistribute it and/or
    + * modify it under the terms of the GNU General Public License
    + * version 2 or 3 as published by the Free Software Foundation.
    + */
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +#include
    +
    +/* Out of tree helper */
    +#if !defined(CONFIG_SECURITY_CAPABILITIES) && \
    + !defined(CONFIG_SECURITY_CAPABILITIES_MODULE)
    +# error You need to have CONFIG_SECURITY_CAPABILITIES=y or =m \
    + for MultiAdmin to compile successfully.
    +#endif
    +
    +#define BASENAME "multiadm"
    +#define PREFIX BASENAME ": "
    +
    +static gid_t Supergid = -1;
    +static gid_t Subgid = -1;
    +static uid_t Superuid_start = 0;
    +static uid_t Superuid_end = 0;
    +static uid_t Subuid_start = -1;
    +static uid_t Subuid_end = -1;
    +static uid_t Wrtuid_start = -1;
    +static uid_t Wrtuid_end = -1;
    +static unsigned int Secondary = 0;
    +
    +module_param(Supergid, int, S_IRUSR | S_IWUSR);
    +module_param(Superuid_start, int, S_IRUSR | S_IWUSR);
    +module_param(Superuid_end, int, S_IRUSR | S_IWUSR);
    +module_param(Subuid_start, int, S_IRUSR | S_IWUSR);
    +module_param(Subuid_end, int, S_IRUSR | S_IWUSR);
    +module_param(Subgid, int, S_IRUSR | S_IWUSR);
    +module_param(Wrtuid_start, int, S_IRUGO | S_IWUSR);
    +module_param(Wrtuid_end, int, S_IRUGO | S_IWUSR);
    +MODULE_PARM_DESC(Wrtuid_start, "First UID of the write-enabled user range");
    +MODULE_PARM_DESC(Wrtuid_end, "Last UID of the write-enabled user range");
    +MODULE_PARM_DESC(Superuid_start, "First UIDs of the superadmin range");
    +MODULE_PARM_DESC(Superuid_end, "Last UID of the superadmin range");
    +MODULE_PARM_DESC(Supergid, "Superadmin GID");
    +MODULE_PARM_DESC(Subuid_start, "First UIDs of the subadmin range");
    +MODULE_PARM_DESC(Subuid_end, "Last UID of the subadmin range");
    +MODULE_PARM_DESC(Subgid, "Subadmin GID");
    +
    +static inline void chg2_superadm(kernel_cap_t *c)
    +{
    + cap_set_full(*c);
    + cap_lower(*c, CAP_SETPCAP);
    + /* Flag 31 is unused, but set */
    + cap_lower(*c, 31);
    + printk(KERN_WARNING "Changed to superadm\n");
    + return;
    +}
    +
    +static inline void chg2_subadm(kernel_cap_t *c)
    +{
    + cap_clear(*c);
    + cap_raise(*c, CAP_CHOWN);
    + cap_raise(*c, CAP_DAC_OVERRIDE);
    + cap_raise(*c, CAP_DAC_READ_SEARCH);
    + cap_raise(*c, CAP_FOWNER);
    + cap_raise(*c, CAP_KILL);
    + cap_raise(*c, CAP_SETUID);
    + cap_raise(*c, CAP_IPC_OWNER);
    + cap_raise(*c, CAP_SYS_PTRACE);
    + cap_raise(*c, CAP_SYS_ADMIN);
    + cap_raise(*c, CAP_SYS_NICE);
    + return;
    +}
    +
    +static inline bool __is_uid_superadm(uid_t u)
    +{
    + return (!issecure(SECURE_NOROOT) && u == 0) ||
    + (Superuid_start != -1 && Superuid_end != -1 &&
    + u >= Superuid_start && u <= Superuid_end);
    +}
    +
    +static inline bool is_uid_superadm(uid_t u)
    +{
    + bool r = __is_uid_superadm(u);
    + printk(KERN_WARNING "You are uid_superadm=%d\n", (int)r);
    + return r;
    +}
    +
    +static inline bool is_gid_superadm(gid_t g)
    +{
    + return Supergid != -1 && g == Supergid;
    +}
    +
    +static inline bool is_any_superadm(uid_t u, gid_t g)
    +{
    + return is_uid_superadm(u) || is_gid_superadm(g);
    +}
    +
    +static inline bool is_uid_subadm(uid_t u)
    +{
    + return Subuid_start != -1 && Subuid_end != -1 &&
    + u >= Subuid_start && u <= Subuid_end;
    +}
    +
    +static inline bool is_gid_subadm(gid_t g)
    +{
    + return Subgid != -1 && g == Subgid;
    +}
    +
    +static inline bool is_any_subadm(uid_t u, gid_t g)
    +{
    + return is_uid_subadm(u) || is_gid_subadm(g);
    +}
    +
    +static inline bool is_uid_user(uid_t u)
    +{
    + /*
    + * Special case Wrtuid_end == (unsigned) -1 means what it means:
    + * everything until the end. This is why there is no
    + * Wrtuid_end != -1 check.
    + */
    + return Wrtuid_start != -1 && u >= Wrtuid_start && u <= Wrtuid_end;
    +}
    +
    +static inline bool is_task1_user(const struct task_struct *task)
    +{
    + return is_uid_user(task->uid) || is_uid_user(task->suid);
    +}
    +
    +static inline bool is_task_user(const struct task_struct *task)
    +{
    + return is_uid_user(task->euid) && is_uid_user(task->uid) &&
    + is_uid_user(task->suid);
    +}
    +
    +static inline bool range_intersect(uid_t as, uid_t ae, uid_t bs, uid_t be)
    +{
    + if(as == -1 || ae == -1 || bs == -1 || be == -1)
    + return 0;
    + return (long)ae >= (long)bs && (long)as <= (long)be;
    +}
    +
    +static inline bool range_intersect_wrt(uid_t as, uid_t ae, uid_t bs, uid_t be)
    +{
    + if(as == -1 || ae == -1 || bs == -1)
    + return 0;
    + return (long)ae >= (long)bs && (long)as <= (long)be;
    +}
    +
    +static int mt_bprm_set_security(struct linux_binprm *bp)
    +{
    + /*
    + * In the function chain of exec(), we eventually get here, which is
    + * the place to set up new privileges.
    + */
    + cap_bprm_set_security(bp);
    +
    + /*
    + * All of the following is nicely inlined. The capability raising is
    + * resolved to only one instruction for each set.
    + */
    + if(is_any_superadm(bp->e_uid, bp->e_gid)) {
    + chg2_superadm(&bp->cap_permitted);
    + chg2_superadm(&bp->cap_effective);
    + } else if(is_any_superadm(current->uid, current->gid)) {
    + chg2_superadm(&bp->cap_permitted);
    + } else if(is_any_subadm(bp->e_uid, bp->e_gid)) {
    + chg2_subadm(&bp->cap_permitted);
    + chg2_subadm(&bp->cap_effective);
    + } else if(is_any_subadm(current->uid, current->gid)) {
    + chg2_subadm(&bp->cap_permitted);
    + }
    + return 0;
    +}
    +
    +static int mt_cap_extra(struct task_struct *task, unsigned int capability)
    +{
    + /*
    + * Subadmin also has CAP_SYS_ADMIN, but if we get here, we did so by
    + * capable() -- not capable_light().
    + */
    + if (capability != CAP_SYS_ADMIN)
    + return 0;
    + if (!is_any_superadm(current->euid, current->egid))
    + return -EPERM;
    + return 0;
    +}
    +
    +static int mt_inode_permission(struct inode *inode, int mask,
    + struct nameidata *nd)
    +{
    + /*
    + * Check for superadmin is not done, since the only users that can get
    + * here is either superadmin or subadmin. By omitting the check for
    + * superadmin, only two comparisons need to be done for the subadmin
    + * case. This method is done almost throughout the entire module.
    + */
    + int ret;
    +
    + if (is_any_subadm(current->euid, current->egid) &&
    + (mask & MAY_WRITE)) {
    + if (inode->i_uid == current->fsuid ||
    + is_uid_user(inode->i_uid))
    + return 0;
    +
    + /*
    + * Since we practically jumped over the checks to get here
    + * (because of CAP_DAC_OVERRIDE), we need to do it again.
    + * Without CAP_DAC_OVERRIDE this time. Temporarily drop it.
    + */
    + cap_lower(current->cap_effective, CAP_DAC_OVERRIDE);
    +
    + /* Copied from fs/namei.c */
    + if (inode->i_op != NULL && inode->i_op->permission != NULL)
    + ret = inode->i_op->permission(inode,
    + mask & ~MAY_APPEND, nd);
    + else
    + ret = generic_permission(inode,
    + mask & ~MAY_APPEND, NULL);
    +
    + cap_raise(current->cap_effective, CAP_DAC_OVERRIDE);
    + return ret;
    + }
    + return 0;
    +}
    +
    +#ifdef APPARMOR
    +static int mt_inode_setattr(struct dentry *dentry, struct vfsmount *vfs,
    + struct iattr *attr)
    +#else
    +static int mt_inode_setattr(struct dentry *dentry, struct iattr *attr)
    +#endif
    +{
    + const struct inode *inode;
    +
    + if (!is_any_subadm(current->euid, current->egid))
    + return 0;
    +
    + /*
    + * Change is only allowed if either the inode belongs to us, or
    + * does belond, _and_ will belong in case of ATTR_UID, to a WRT
    + * user.
    + */
    + inode = dentry->d_inode;
    +
    + if (inode->i_uid != current->fsuid && !is_uid_user(inode->i_uid))
    + return -EPERM;
    +
    + if ((attr->ia_valid & ATTR_UID) && attr->ia_uid != current->fsuid &&
    + !is_uid_user(attr->ia_uid))
    + return -EPERM;
    +
    + return 0;
    +}
    +
    +static int mt_ipc_permission(struct kern_ipc_perm *perm, short flag)
    +{
    + int req, grant;
    + if (!is_any_subadm(current->euid, current->egid))
    + return 0;
    +
    + if (perm->uid == current->euid || perm->cuid == current->euid ||
    + is_uid_user(perm->uid) || is_uid_user(perm->cuid))
    + return 0;
    +
    + /*
    + * Copied and modified from ipc/util.c. Subadmin always has read
    + * permission so add S_IRUGO to granted. Checking the owner permission
    + * part is not done anymore, because it is done above.
    + */
    + req = (flag >> 6) | (flag >> 3) | flag;
    + grant = (perm->mode | S_IRUGO) >> 3;
    + if(in_group_p(perm->gid) || in_group_p(perm->cgid))
    + grant >>= 3;
    + if(req & ~grant & 0007)
    + return -EPERM;
    + return 0;
    +}
    +
    +static int mt_msq_msgctl(struct msg_queue *msq, int cmd)
    +{
    + if (!is_any_subadm(current->euid, current->egid))
    + return 0;
    +
    + if (cmd == MSG_INFO || cmd == MSG_STAT ||
    + cmd == IPC_INFO || cmd == IPC_STAT)
    + return 0;
    +
    + /* UID or CUID (creator UID) must fit */
    + if (msq != NULL && msq->q_perm.uid != current->euid &&
    + msq->q_perm.cuid != current->euid &&
    + !is_uid_user(msq->q_perm.uid) && !is_uid_user(msq->q_perm.cuid))
    + return -EPERM;
    +
    + return 0;
    +}
    +
    +static int mt_ptrace(struct task_struct *tracer, struct task_struct *task)
    +{
    + if (!is_any_subadm(tracer->euid, tracer->egid))
    + return 0;
    +
    + /*
    + * Ownership check according to kernel/ptrace.c:
    + * all of [RES][UG]ID must match the tracer's R[UG]ID.
    + */
    + if (task->euid == tracer->uid && task->uid == tracer->uid &&
    + task->suid == tracer->uid && task->egid == tracer->gid &&
    + task->gid == tracer->gid && task->sgid == tracer->gid)
    + return 0;
    +
    + /* ...or all [RES]UIDs must match a WRT user */
    + if (!is_task_user(task))
    + return -EPERM;
    + return 0;
    +}
    +
    +static int mt_quotactl(int cmd, int type, int id, struct super_block *sb)
    +{
    + if (!is_any_subadm(current->euid, current->egid))
    + return 0;
    +
    + switch(cmd) {
    + case Q_SYNC:
    + case Q_GETFMT:
    + case Q_GETINFO:
    + case Q_GETQUOTA:
    + case Q_XGETQUOTA:
    + case Q_XGETQSTAT:
    + case Q_XQUOTASYNC:
    + return 0;
    + }
    + return -EPERM;
    +}
    +
    +static int mt_sem_semctl(struct sem_array *sem, int cmd)
    +{
    + if (!is_any_subadm(current->euid, current->euid))
    + return 0;
    +
    + if (cmd == SEM_INFO || cmd == IPC_INFO || cmd == SEM_STAT)
    + return 0;
    + if (sem != NULL) {
    + const struct kern_ipc_perm *perm = &sem->sem_perm;
    +
    + if (perm->uid != current->euid &&
    + perm->cuid != current->euid &&
    + !is_uid_user(perm->uid) && !is_uid_user(perm->cuid))
    + return -EPERM;
    + }
    + return 0;
    +}
    +
    +static int mt_shm_shmctl(struct shmid_kernel *shp, int cmd)
    +{
    + if (!is_any_subadm(current->euid, current->egid))
    + return 0;
    +
    + if (cmd == SHM_INFO || cmd == SHM_STAT ||
    + cmd == IPC_INFO || cmd == IPC_STAT)
    + return 0;
    + if (shp != NULL) {
    + const struct kern_ipc_perm *perm = &shp->shm_perm;
    +
    + if (perm->uid != current->euid &&
    + perm->cuid != current->euid &&
    + !is_uid_user(perm->uid) && !is_uid_user(perm->cuid))
    + return -EPERM;
    + }
    + return 0;
    +}
    +
    +static int mt_task_kill(struct task_struct *task, struct siginfo *si,
    + int sig, u32 secid)
    +{
    + if (!is_any_subadm(current->euid, current->egid))
    + return 0;
    +
    + /* As tricky as the ptrace() permission net. */
    + if(is_uid_user(task->uid) || is_uid_user(task->suid))
    + return 0;
    +
    + /* Subadmin's own process */
    + if (task->uid == current->euid || task->suid == current->euid ||
    + task->uid == current->uid || task->suid == current->uid)
    + return 0;
    +
    + /* SIG_IGN or a kernel-generated signal */
    + if (si != NULL && ((long)si == 1 || (long)si == 2 || !SI_FROMUSER(si)))
    + return 0;
    +
    + /* For the case of a privileged subshell, but with the same tty */
    + if (sig == SIGCONT &&
    + task->signal->__session == current->signal->__session)
    + return 0;
    +
    + return -EPERM;
    +}
    +
    +static int mt_task_post_setuid(uid_t old_ruid, uid_t old_euid,
    + uid_t old_suid, int flags)
    +{
    + int ret = cap_task_post_setuid(old_ruid, old_euid, old_suid, flags);
    +
    + if (ret != 0)
    + return ret;
    +
    + switch (flags) {
    + case LSM_SETID_ID:
    + case LSM_SETID_RE:
    + case LSM_SETID_RES:
    + /*
    + * Unlike bprm_set_security(), effective must be set
    + * independently.
    + */
    + if (is_uid_superadm(current->uid))
    + chg2_superadm(&current->cap_permitted);
    + else if (is_uid_subadm(current->uid))
    + chg2_subadm(&current->cap_permitted);
    +
    + if (is_uid_superadm(current->euid))
    + chg2_superadm(&current->cap_effective);
    + else if (is_uid_subadm(current->euid))
    + chg2_subadm(&current->cap_effective);
    + break;
    + }
    + return 0;
    +}
    +
    +static int mt_task_post_setgid(gid_t old_rgid, gid_t old_egid,
    + gid_t old_sgid, unsigned int flags)
    +{
    + switch (flags) {
    + case LSM_SETID_ID:
    + case LSM_SETID_RE:
    + case LSM_SETID_RES:
    + if (is_gid_superadm(current->gid))
    + chg2_superadm(&current->cap_permitted);
    + else if (is_gid_subadm(current->gid))
    + chg2_subadm(&current->cap_permitted);
    +
    + if (is_gid_superadm(current->egid))
    + chg2_superadm(&current->cap_effective);
    + else if (is_gid_subadm(current->egid))
    + chg2_subadm(&current->cap_effective);
    + break;
    + }
    + return 0;
    +}
    +
    +static int mt_task_setuid(uid_t ruid, uid_t euid, uid_t suid, int flags)
    +{
    + if (is_any_superadm(current->euid, current->egid))
    + return 0;
    +
    + if (is_any_subadm(current->euid, current->egid))
    + if ((ruid == -1 || is_uid_user(ruid)) &&
    + (euid == -1 || is_uid_user(euid)) &&
    + (suid == -1 || is_uid_user(suid)))
    + return 0;
    +
    + switch (flags) {
    + case LSM_SETID_ID:
    + if (current->uid == ruid || current->suid == ruid)
    + return 0;
    + break;
    + case LSM_SETID_RE:
    + if (current->euid == ruid || current->euid == euid ||
    + current->uid == ruid || current->uid == euid ||
    + current->suid == euid)
    + return 0;
    + break;
    + case LSM_SETID_RES:
    + if (current->euid == ruid || current->euid == euid ||
    + current->euid == suid || current->uid == ruid ||
    + current->uid == euid || current->uid == suid ||
    + current->suid == ruid || current->suid == euid ||
    + current->suid == suid)
    + return 0;
    + break;
    + case LSM_SETID_FS:
    + if (current->euid == ruid)
    + return 0;
    + break;
    + default:
    + WARN_ON(1);
    + break;
    + }
    + return -EPERM;
    +}
    +
    +static int mt_task_setnice(struct task_struct *task, int nice)
    +{
    + if (!is_any_subadm(current->euid, current->egid))
    + return 0;
    + if (task->euid != current->euid && task->uid != current->euid &&
    + !is_task1_user(task))
    + return -EPERM;
    + if (nice < 0)
    + return -EACCES;
    + return 0;
    +}
    +
    +static int mt_task_setscheduler(struct task_struct *task, int policy,
    + struct sched_param *param)
    +{
    + /*
    + * Return 0 for superuser and normal users. The latters' checks are
    + * performed in sched.c.
    + */
    + if (!is_any_subadm(current->euid, current->egid))
    + return 0;
    +
    + /* Copied from kernel/sched.c:sched_setscheduler() */
    + if (task->policy != policy)
    + return -EPERM;
    +
    + if (policy != SCHED_NORMAL &&
    + param->sched_priority > task->rt_priority &&
    + param->sched_priority > task->signal->rlim[RLIMIT_RTPRIO].rlim_cur)
    + return -EPERM;
    +
    + if (task->uid != current->euid && task->suid != current->euid &&
    + !is_task1_user(task))
    + return -EPERM;
    +
    + return 0;
    +}
    +
    +static struct security_operations mt_secops = {
    + .bprm_apply_creds = cap_bprm_apply_creds,
    + .bprm_set_security = mt_bprm_set_security,
    + .cap_extra = mt_cap_extra,
    + .capable = cap_capable,
    + .capget = cap_capget,
    + .capset_check = cap_capset_check,
    + .capset_set = cap_capset_set,
    + .inode_permission = mt_inode_permission,
    + .inode_setattr = mt_inode_setattr,
    + .ipc_permission = mt_ipc_permission,
    + .msg_queue_msgctl = mt_msq_msgctl,
    + .ptrace = mt_ptrace,
    + .quotactl = mt_quotactl,
    + .sem_semctl = mt_sem_semctl,
    + .shm_shmctl = mt_shm_shmctl,
    + .task_kill = mt_task_kill,
    + .task_post_setuid = mt_task_post_setuid,
    + .task_post_setgid = mt_task_post_setgid,
    + .task_setnice = mt_task_setnice,
    + .task_setscheduler = mt_task_setscheduler,
    + .task_setuid = mt_task_setuid,
    +};
    +
    +static __init int multiadm_init(void)
    +{
    + int ret, ret2;
    +
    + if ((ret = register_security(&mt_secops)) != 0) {
    + if ((ret2 = mod_reg_security(BASENAME, &mt_secops)) != 0) {
    + printk(KERN_WARNING PREFIX "Could not register with "
    + "kernel: %d, %d\n", ret, ret2);
    + return ret2;
    + }
    + Secondary = 1;
    + }
    +
    + if (range_intersect(Superuid_start, Superuid_end,
    + Subuid_start, Subuid_end))
    + printk(KERN_WARNING PREFIX
    + "Superadmin and Subadmin ranges intersect! "
    + "Unpredictable behavior may result: some operations "
    + "may classify you as a superadmin, others as a "
    + "subadmin. Security leak: subadmin could possibly "
    + "change into superadmin!\n");
    +
    + if (range_intersect(Superuid_start, Superuid_end,
    + Wrtuid_start, Wrtuid_end))
    + printk(KERN_WARNING PREFIX
    + "Superadmin and write-enabled user range intersect! "
    + "A subadmin could setuid() into a superadmin!\n");
    +
    + if (range_intersect_wrt(Subuid_start, Subuid_end,
    + Wrtuid_start, Wrtuid_end))
    + printk(KERN_WARNING PREFIX
    + "Subadmin and write-enabled user range intersect! "
    + "Subadmins are able to poke on other subadmins!\n");
    +
    + printk(KERN_INFO "MultiAdmin loaded\n");
    + return 0;
    +}
    +
    +static __exit void multiadm_exit(void)
    +{
    + int ret = 0;
    +
    + if(Secondary)
    + ret = mod_unreg_security(BASENAME, &mt_secops);
    + else
    + ret = unregister_security(&mt_secops);
    +
    + if(ret != 0)
    + printk(KERN_WARNING PREFIX
    + "Could not unregister with kernel: %d\n", ret);
    +
    + return;
    +}
    +
    +module_init(multiadm_init);
    +module_exit(multiadm_exit);
    +MODULE_DESCRIPTION("MultiAdmin Security Module");
    +MODULE_AUTHOR("Jan Engelhardt ");
    +MODULE_LICENSE("GPL");
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  3. [PATCH 1/4] MultiAdmin 1.0.7


    [PATCH 1/4] security_cap_extra() and more

    - Renames capable() to capable_light().
    This function is used if only a capability is to be checked.

    - Implement a new capable that calls security_cap_extra().
    Since a subadmin has almost the same capabilities as a
    superadmin, an extra helper is needed to decide whether an
    action is allowed, based on the philosophy of the LSM.

    - implement the .cap_extra LSM hook


    Signed-off-by: Jan Engelhardt , May 01 2006
    July 11 2006

    ---
    include/linux/capability.h | 2 ++
    include/linux/security.h | 13 +++++++++++++
    kernel/capability.c | 19 ++++++++++++++++++-
    security/dummy.c | 6 ++++++
    4 files changed, 39 insertions(+), 1 deletion(-)

    Index: linux-2.6.23.1/include/linux/capability.h
    ================================================== =================
    --- linux-2.6.23.1.orig/include/linux/capability.h
    +++ linux-2.6.23.1/include/linux/capability.h
    @@ -358,6 +358,8 @@ static inline kernel_cap_t cap_invert(ke

    #define cap_is_fs_cap(c) (CAP_TO_MASK(c) & CAP_FS_MASK)

    +bool capable_light(unsigned int);
    +bool __capable_light(struct task_struct *, unsigned int);
    int capable(int cap);
    int __capable(struct task_struct *t, int cap);

    Index: linux-2.6.23.1/include/linux/security.h
    ================================================== =================
    --- linux-2.6.23.1.orig/include/linux/security.h
    +++ linux-2.6.23.1/include/linux/security.h
    @@ -1399,6 +1399,7 @@ struct security_operations {

    #endif /* CONFIG_KEYS */

    + int (*cap_extra)(struct task_struct *, unsigned int);
    };

    /* global variables */
    @@ -2132,6 +2133,12 @@ static inline void security_release_secc
    return security_ops->release_secctx(secdata, seclen);
    }

    +static inline int security_cap_extra(struct task_struct *task,
    + unsigned int cap)
    +{
    + return security_ops->cap_extra(task, cap);
    +}
    +
    /* prototypes */
    extern int security_init (void);
    extern int register_security (struct security_operations *ops);
    @@ -2786,6 +2793,12 @@ static inline int security_netlink_recv
    return cap_netlink_recv (skb, cap);
    }

    +static inline int security_cap_extra(struct task_struct *task,
    + unsigned int cap)
    +{
    + return 0;
    +}
    +
    static inline struct dentry *securityfs_create_dir(const char *name,
    struct dentry *parent)
    {
    Index: linux-2.6.23.1/kernel/capability.c
    ================================================== =================
    --- linux-2.6.23.1.orig/kernel/capability.c
    +++ linux-2.6.23.1/kernel/capability.c
    @@ -238,7 +238,7 @@ out:

    int __capable(struct task_struct *t, int cap)
    {
    - if (security_capable(t, cap) == 0) {
    + if (security_capable(t, cap) == 0 && security_cap_extra(t, cap) == 0) {
    t->flags |= PF_SUPERPRIV;
    return 1;
    }
    @@ -251,3 +251,20 @@ int capable(int cap)
    return __capable(current, cap);
    }
    EXPORT_SYMBOL(capable);
    +
    +bool __capable_light(struct task_struct *t, unsigned int cap)
    +{
    + if (security_capable(t, cap) == 0) {
    + t->flags |= PF_SUPERPRIV;
    + return true;
    + }
    + return false;
    +}
    +EXPORT_SYMBOL(__capable_light);
    +
    +bool capable_light(unsigned int cap)
    +{
    + return __capable_light(current, cap);
    +}
    +EXPORT_SYMBOL(capable_light);
    +
    Index: linux-2.6.23.1/security/dummy.c
    ================================================== =================
    --- linux-2.6.23.1.orig/security/dummy.c
    +++ linux-2.6.23.1/security/dummy.c
    @@ -693,6 +693,11 @@ static int dummy_netlink_recv (struct sk
    return 0;
    }

    +static int dummy_cap_extra(struct task_struct *task, unsigned int cap)
    +{
    + return 0;
    +}
    +
    #ifdef CONFIG_SECURITY_NETWORK
    static int dummy_unix_stream_connect (struct socket *sock,
    struct socket *other,
    @@ -1132,5 +1137,6 @@ void security_fixup_ops (struct security
    set_to_dummy_if_null(ops, key_permission);
    #endif /* CONFIG_KEYS */

    + set_to_dummy_if_null(ops, cap_extra);
    }

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  4. [PATCH 3/4] MultiAdmin 1.0.7


    [PATCH 3/4] task_post_setgid()

    - Implement the task_post_setgid() LSM hook which is required by
    MultiAdmin to switch between classes.
    (task_post_setuid also switches between classes -- and already exists)


    Signed-off-by: Jan Engelhardt , May 01 2006
    Modified July 11 2006

    ---
    include/linux/security.h | 13 +++++++++++++
    kernel/sys.c | 15 ++++++++++++---
    security/dummy.c | 7 +++++++
    3 files changed, 32 insertions(+), 3 deletions(-)

    Index: linux-2.6.23.1/include/linux/security.h
    ================================================== =================
    --- linux-2.6.23.1.orig/include/linux/security.h
    +++ linux-2.6.23.1/include/linux/security.h
    @@ -1400,6 +1400,7 @@ struct security_operations {
    #endif /* CONFIG_KEYS */

    int (*cap_extra)(struct task_struct *, unsigned int);
    + int (*task_post_setgid)(gid_t, gid_t, gid_t, unsigned int);
    };

    /* global variables */
    @@ -2139,6 +2140,12 @@ static inline int security_cap_extra(str
    return security_ops->cap_extra(task, cap);
    }

    +static inline int security_task_post_setgid(gid_t real, gid_t effective,
    + gid_t saved, unsigned int type)
    +{
    + return security_ops->task_post_setgid(real, effective, saved, type);
    +}
    +
    /* prototypes */
    extern int security_init (void);
    extern int register_security (struct security_operations *ops);
    @@ -2799,6 +2806,12 @@ static inline int security_cap_extra(str
    return 0;
    }

    +static inline int security_task_post_setgid(gid_t real, gid_t effective,
    + gid_t saved, unsigned int type)
    +{
    + return 0;
    +}
    +
    static inline struct dentry *securityfs_create_dir(const char *name,
    struct dentry *parent)
    {
    Index: linux-2.6.23.1/kernel/sys.c
    ================================================== =================
    --- linux-2.6.23.1.orig/kernel/sys.c
    +++ linux-2.6.23.1/kernel/sys.c
    @@ -1052,7 +1052,8 @@ asmlinkage long sys_setregid(gid_t rgid,
    current->gid = new_rgid;
    key_fsgid_changed(current);
    proc_id_connector(current, PROC_EVENT_GID);
    - return 0;
    + return security_task_post_setgid(old_rgid, old_egid,
    + (gid_t)-1, LSM_SETID_RE);
    }

    /*
    @@ -1062,6 +1063,7 @@ asmlinkage long sys_setregid(gid_t rgid,
    */
    asmlinkage long sys_setgid(gid_t gid)
    {
    + gid_t old_rgid = current->gid;
    int old_egid = current->egid;
    int retval;

    @@ -1087,7 +1089,8 @@ asmlinkage long sys_setgid(gid_t gid)

    key_fsgid_changed(current);
    proc_id_connector(current, PROC_EVENT_GID);
    - return 0;
    + return security_task_post_setgid(old_rgid, (gid_t)-1,
    + (gid_t)-1, LSM_SETID_ID);
    }

    static int set_user(uid_t new_ruid, int dumpclear)
    @@ -1290,6 +1293,9 @@ asmlinkage long sys_getresuid(uid_t __us
    */
    asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
    {
    + gid_t old_rgid = current->gid;
    + gid_t old_egid = current->egid;
    + gid_t old_sgid = current->sgid;
    int retval;

    retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
    @@ -1322,7 +1328,8 @@ asmlinkage long sys_setresgid(gid_t rgid

    key_fsgid_changed(current);
    proc_id_connector(current, PROC_EVENT_GID);
    - return 0;
    + return security_task_post_setgid(old_rgid, old_egid,
    + old_sgid, LSM_SETID_RES);
    }

    asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid)
    @@ -1391,6 +1398,8 @@ asmlinkage long sys_setfsgid(gid_t gid)
    key_fsgid_changed(current);
    proc_id_connector(current, PROC_EVENT_GID);
    }
    + security_task_post_setgid(old_fsgid, (gid_t)-1,
    + (gid_t)-1, LSM_SETID_FS);
    return old_fsgid;
    }

    Index: linux-2.6.23.1/security/dummy.c
    ================================================== =================
    --- linux-2.6.23.1.orig/security/dummy.c
    +++ linux-2.6.23.1/security/dummy.c
    @@ -698,6 +698,12 @@ static int dummy_cap_extra(struct task_s
    return 0;
    }

    +static int dummy_task_post_setgid(gid_t real, gid_t effective,
    + gid_t saved, unsigned int type)
    +{
    + return 0;
    +}
    +
    #ifdef CONFIG_SECURITY_NETWORK
    static int dummy_unix_stream_connect (struct socket *sock,
    struct socket *other,
    @@ -1138,5 +1144,6 @@ void security_fixup_ops (struct security
    #endif /* CONFIG_KEYS */

    set_to_dummy_if_null(ops, cap_extra);
    + set_to_dummy_if_null(ops, task_post_setgid);
    }

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  5. Re: [PATCH 0/4] MultiAdmin 1.0.7


    [PATCH 3/4] task_post_setgid()

    - Implement the task_post_setgid() LSM hook which is required by
    MultiAdmin to switch between classes.
    (task_post_setuid also switches between classes -- and already exists)


    Signed-off-by: Jan Engelhardt , May 01 2006
    Modified July 11 2006

    ---
    include/linux/security.h | 13 +++++++++++++
    kernel/sys.c | 15 ++++++++++++---
    security/dummy.c | 7 +++++++
    3 files changed, 32 insertions(+), 3 deletions(-)

    Index: linux-2.6.23.1/include/linux/security.h
    ================================================== =================
    --- linux-2.6.23.1.orig/include/linux/security.h
    +++ linux-2.6.23.1/include/linux/security.h
    @@ -1400,6 +1400,7 @@ struct security_operations {
    #endif /* CONFIG_KEYS */

    int (*cap_extra)(struct task_struct *, unsigned int);
    + int (*task_post_setgid)(gid_t, gid_t, gid_t, unsigned int);
    };

    /* global variables */
    @@ -2139,6 +2140,12 @@ static inline int security_cap_extra(str
    return security_ops->cap_extra(task, cap);
    }

    +static inline int security_task_post_setgid(gid_t real, gid_t effective,
    + gid_t saved, unsigned int type)
    +{
    + return security_ops->task_post_setgid(real, effective, saved, type);
    +}
    +
    /* prototypes */
    extern int security_init (void);
    extern int register_security (struct security_operations *ops);
    @@ -2799,6 +2806,12 @@ static inline int security_cap_extra(str
    return 0;
    }

    +static inline int security_task_post_setgid(gid_t real, gid_t effective,
    + gid_t saved, unsigned int type)
    +{
    + return 0;
    +}
    +
    static inline struct dentry *securityfs_create_dir(const char *name,
    struct dentry *parent)
    {
    Index: linux-2.6.23.1/kernel/sys.c
    ================================================== =================
    --- linux-2.6.23.1.orig/kernel/sys.c
    +++ linux-2.6.23.1/kernel/sys.c
    @@ -1052,7 +1052,8 @@ asmlinkage long sys_setregid(gid_t rgid,
    current->gid = new_rgid;
    key_fsgid_changed(current);
    proc_id_connector(current, PROC_EVENT_GID);
    - return 0;
    + return security_task_post_setgid(old_rgid, old_egid,
    + (gid_t)-1, LSM_SETID_RE);
    }

    /*
    @@ -1062,6 +1063,7 @@ asmlinkage long sys_setregid(gid_t rgid,
    */
    asmlinkage long sys_setgid(gid_t gid)
    {
    + gid_t old_rgid = current->gid;
    int old_egid = current->egid;
    int retval;

    @@ -1087,7 +1089,8 @@ asmlinkage long sys_setgid(gid_t gid)

    key_fsgid_changed(current);
    proc_id_connector(current, PROC_EVENT_GID);
    - return 0;
    + return security_task_post_setgid(old_rgid, (gid_t)-1,
    + (gid_t)-1, LSM_SETID_ID);
    }

    static int set_user(uid_t new_ruid, int dumpclear)
    @@ -1290,6 +1293,9 @@ asmlinkage long sys_getresuid(uid_t __us
    */
    asmlinkage long sys_setresgid(gid_t rgid, gid_t egid, gid_t sgid)
    {
    + gid_t old_rgid = current->gid;
    + gid_t old_egid = current->egid;
    + gid_t old_sgid = current->sgid;
    int retval;

    retval = security_task_setgid(rgid, egid, sgid, LSM_SETID_RES);
    @@ -1322,7 +1328,8 @@ asmlinkage long sys_setresgid(gid_t rgid

    key_fsgid_changed(current);
    proc_id_connector(current, PROC_EVENT_GID);
    - return 0;
    + return security_task_post_setgid(old_rgid, old_egid,
    + old_sgid, LSM_SETID_RES);
    }

    asmlinkage long sys_getresgid(gid_t __user *rgid, gid_t __user *egid, gid_t __user *sgid)
    @@ -1391,6 +1398,8 @@ asmlinkage long sys_setfsgid(gid_t gid)
    key_fsgid_changed(current);
    proc_id_connector(current, PROC_EVENT_GID);
    }
    + security_task_post_setgid(old_fsgid, (gid_t)-1,
    + (gid_t)-1, LSM_SETID_FS);
    return old_fsgid;
    }

    Index: linux-2.6.23.1/security/dummy.c
    ================================================== =================
    --- linux-2.6.23.1.orig/security/dummy.c
    +++ linux-2.6.23.1/security/dummy.c
    @@ -698,6 +698,12 @@ static int dummy_cap_extra(struct task_s
    return 0;
    }

    +static int dummy_task_post_setgid(gid_t real, gid_t effective,
    + gid_t saved, unsigned int type)
    +{
    + return 0;
    +}
    +
    #ifdef CONFIG_SECURITY_NETWORK
    static int dummy_unix_stream_connect (struct socket *sock,
    struct socket *other,
    @@ -1138,5 +1144,6 @@ void security_fixup_ops (struct security
    #endif /* CONFIG_KEYS */

    set_to_dummy_if_null(ops, cap_extra);
    + set_to_dummy_if_null(ops, task_post_setgid);
    }

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  6. [PATCH 2/4] MultiAdmin 1.0.7


    [PATCH 2/4] Use of capable_light()

    capable() now behaves like (capable_light() && is_superadm). Since some
    operations are allowed by subadmins too, it suffices to use
    capable_light().


    Signed-off-by: Jan Engelhardt , May 01 2006
    Modified July 11 2006

    ---
    arch/alpha/kernel/pci-noop.c | 2 +-
    drivers/char/lp.c | 2 +-
    drivers/firmware/efivars.c | 2 +-
    drivers/pci/pci-sysfs.c | 2 +-
    drivers/pci/proc.c | 2 +-
    drivers/pci/syscall.c | 2 +-
    fs/quota.c | 8 ++++----
    ipc/msg.c | 2 +-
    ipc/sem.c | 2 +-
    ipc/shm.c | 4 ++--
    10 files changed, 14 insertions(+), 14 deletions(-)

    Index: linux-2.6.23.1/arch/alpha/kernel/pci-noop.c
    ================================================== =================
    --- linux-2.6.23.1.orig/arch/alpha/kernel/pci-noop.c
    +++ linux-2.6.23.1/arch/alpha/kernel/pci-noop.c
    @@ -89,7 +89,7 @@ asmlinkage long
    sys_pciconfig_read(unsigned long bus, unsigned long dfn,
    unsigned long off, unsigned long len, void *buf)
    {
    - if (!capable(CAP_SYS_ADMIN))
    + if (!capable_light(CAP_SYS_ADMIN))
    return -EPERM;
    else
    return -ENODEV;
    Index: linux-2.6.23.1/drivers/char/lp.c
    ================================================== =================
    --- linux-2.6.23.1.orig/drivers/char/lp.c
    +++ linux-2.6.23.1/drivers/char/lp.c
    @@ -627,7 +627,7 @@ static int lp_ioctl(struct inode *inode,
    if (copy_to_user(argp, &LP_STAT(minor),
    sizeof(struct lp_stats)))
    return -EFAULT;
    - if (capable(CAP_SYS_ADMIN))
    + if (capable_light(CAP_SYS_ADMIN))
    memset(&LP_STAT(minor), 0,
    sizeof(struct lp_stats));
    break;
    Index: linux-2.6.23.1/drivers/firmware/efivars.c
    ================================================== =================
    --- linux-2.6.23.1.orig/drivers/firmware/efivars.c
    +++ linux-2.6.23.1/drivers/firmware/efivars.c
    @@ -351,7 +351,7 @@ static ssize_t efivar_attr_show(struct k
    struct efivar_attribute *efivar_attr = to_efivar_attr(attr);
    ssize_t ret = -EIO;

    - if (!capable(CAP_SYS_ADMIN))
    + if (!capable_light(CAP_SYS_ADMIN))
    return -EACCES;

    if (efivar_attr->show) {
    Index: linux-2.6.23.1/drivers/pci/pci-sysfs.c
    ================================================== =================
    --- linux-2.6.23.1.orig/drivers/pci/pci-sysfs.c
    +++ linux-2.6.23.1/drivers/pci/pci-sysfs.c
    @@ -222,7 +222,7 @@ pci_read_config(struct kobject *kobj, st
    u8 *data = (u8*) buf;

    /* Several chips lock up trying to read undefined config space */
    - if (capable(CAP_SYS_ADMIN)) {
    + if (capable_light(CAP_SYS_ADMIN)) {
    size = dev->cfg_size;
    } else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS) {
    size = 128;
    Index: linux-2.6.23.1/drivers/pci/proc.c
    ================================================== =================
    --- linux-2.6.23.1.orig/drivers/pci/proc.c
    +++ linux-2.6.23.1/drivers/pci/proc.c
    @@ -59,7 +59,7 @@ proc_bus_pci_read(struct file *file, cha
    * undefined locations (think of Intel PIIX4 as a typical example).
    */

    - if (capable(CAP_SYS_ADMIN))
    + if (capable_light(CAP_SYS_ADMIN))
    size = dev->cfg_size;
    else if (dev->hdr_type == PCI_HEADER_TYPE_CARDBUS)
    size = 128;
    Index: linux-2.6.23.1/drivers/pci/syscall.c
    ================================================== =================
    --- linux-2.6.23.1.orig/drivers/pci/syscall.c
    +++ linux-2.6.23.1/drivers/pci/syscall.c
    @@ -26,7 +26,7 @@ sys_pciconfig_read(unsigned long bus, un
    long err;
    long cfg_ret;

    - if (!capable(CAP_SYS_ADMIN))
    + if (!capable_light(CAP_SYS_ADMIN))
    return -EPERM;

    err = -ENODEV;
    Index: linux-2.6.23.1/fs/quota.c
    ================================================== =================
    --- linux-2.6.23.1.orig/fs/quota.c
    +++ linux-2.6.23.1/fs/quota.c
    @@ -82,11 +82,11 @@ static int generic_quotactl_valid(struct
    if (cmd == Q_GETQUOTA) {
    if (((type == USRQUOTA && current->euid != id) ||
    (type == GRPQUOTA && !in_egroup_p(id))) &&
    - !capable(CAP_SYS_ADMIN))
    + !capable_light(CAP_SYS_ADMIN))
    return -EPERM;
    }
    else if (cmd != Q_GETFMT && cmd != Q_SYNC && cmd != Q_GETINFO)
    - if (!capable(CAP_SYS_ADMIN))
    + if (!capable_light(CAP_SYS_ADMIN))
    return -EPERM;

    return 0;
    @@ -133,10 +133,10 @@ static int xqm_quotactl_valid(struct sup
    if (cmd == Q_XGETQUOTA) {
    if (((type == XQM_USRQUOTA && current->euid != id) ||
    (type == XQM_GRPQUOTA && !in_egroup_p(id))) &&
    - !capable(CAP_SYS_ADMIN))
    + !capable_light(CAP_SYS_ADMIN))
    return -EPERM;
    } else if (cmd != Q_XGETQSTAT && cmd != Q_XQUOTASYNC) {
    - if (!capable(CAP_SYS_ADMIN))
    + if (!capable_light(CAP_SYS_ADMIN))
    return -EPERM;
    }

    Index: linux-2.6.23.1/ipc/msg.c
    ================================================== =================
    --- linux-2.6.23.1.orig/ipc/msg.c
    +++ linux-2.6.23.1/ipc/msg.c
    @@ -518,7 +518,7 @@ asmlinkage long sys_msgctl(int msqid, in

    err = -EPERM;
    if (current->euid != ipcp->cuid &&
    - current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN))
    + current->euid != ipcp->uid && !capable_light(CAP_SYS_ADMIN))
    /* We _could_ check for CAP_CHOWN above, but we don't */
    goto out_unlock_up;

    Index: linux-2.6.23.1/ipc/sem.c
    ================================================== =================
    --- linux-2.6.23.1.orig/ipc/sem.c
    +++ linux-2.6.23.1/ipc/sem.c
    @@ -883,7 +883,7 @@ static int semctl_down(struct ipc_namesp
    goto out_unlock;
    }
    if (current->euid != ipcp->cuid &&
    - current->euid != ipcp->uid && !capable(CAP_SYS_ADMIN)) {
    + current->euid != ipcp->uid && !capable_light(CAP_SYS_ADMIN)) {
    err=-EPERM;
    goto out_unlock;
    }
    Index: linux-2.6.23.1/ipc/shm.c
    ================================================== =================
    --- linux-2.6.23.1.orig/ipc/shm.c
    +++ linux-2.6.23.1/ipc/shm.c
    @@ -756,7 +756,7 @@ asmlinkage long sys_shmctl (int shmid, i

    if (current->euid != shp->shm_perm.uid &&
    current->euid != shp->shm_perm.cuid &&
    - !capable(CAP_SYS_ADMIN)) {
    + !capable_light(CAP_SYS_ADMIN)) {
    err=-EPERM;
    goto out_unlock_up;
    }
    @@ -793,7 +793,7 @@ asmlinkage long sys_shmctl (int shmid, i
    err=-EPERM;
    if (current->euid != shp->shm_perm.uid &&
    current->euid != shp->shm_perm.cuid &&
    - !capable(CAP_SYS_ADMIN)) {
    + !capable_light(CAP_SYS_ADMIN)) {
    goto out_unlock_up;
    }

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

  7. Re: [PATCH 0/4] MultiAdmin 1.0.7

    On Sun, 21 Oct 2007 01:51:50 +0200 (CEST)
    Jan Engelhardt wrote:

    > As per James's request, I am reposting the MultiAdmin LSM


    That's very nice, but ... what is it?

    It would be really helpful if each patch series came with some
    kind of description of what problem the patches try to solve
    and how it solves it

    --
    "Debugging is twice as hard as writing the code in the first place.
    Therefore, if you write the code as cleverly as possible, you are,
    by definition, not smart enough to debug it." - Brian W. Kernighan
    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/

+ Reply to Thread