Skip to content

Commit

Permalink
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel…
Browse files Browse the repository at this point in the history
…/git/jmorris/security-testing-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (43 commits)
  TOMOYO: Fix wrong domainname validation.
  SELINUX: add /sys/fs/selinux mount point to put selinuxfs
  CRED: Fix load_flat_shared_library() to initialise bprm correctly
  SELinux: introduce path_has_perm
  flex_array: allow 0 length elements
  flex_arrays: allow zero length flex arrays
  flex_array: flex_array_prealloc takes a number of elements, not an end
  SELinux: pass last path component in may_create
  SELinux: put name based create rules in a hashtable
  SELinux: generic hashtab entry counter
  SELinux: calculate and print hashtab stats with a generic function
  SELinux: skip filename trans rules if ttype does not match parent dir
  SELinux: rename filename_compute_type argument to *type instead of *con
  SELinux: fix comment to state filename_compute_type takes an objname not a qstr
  SMACK: smack_file_lock can use the struct path
  LSM: separate LSM_AUDIT_DATA_DENTRY from LSM_AUDIT_DATA_PATH
  LSM: split LSM_AUDIT_DATA_FS into _PATH and _INODE
  SELINUX: Make selinux cache VFS RCU walks safe
  SECURITY: Move exec_permission RCU checks into security modules
  SELinux: security_read_policy should take a size_t not ssize_t
  ...
  • Loading branch information
torvalds committed May 24, 2011
2 parents 2bb732c + b7b5755 commit b0ca118
Show file tree
Hide file tree
Showing 39 changed files with 603 additions and 284 deletions.
3 changes: 2 additions & 1 deletion MAINTAINERS
Original file line number Diff line number Diff line change
Expand Up @@ -5592,10 +5592,11 @@ M: James Morris <[email protected]>
M: Eric Paris <[email protected]>
L: [email protected] (subscribers-only, general discussion)
W: http://selinuxproject.org
T: git git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6.git
T: git git://git.infradead.org/users/eparis/selinux.git
S: Supported
F: include/linux/selinux*
F: security/selinux/
F: scripts/selinux/

APPARMOR SECURITY MODULE
M: John Johansen <[email protected]>
Expand Down
8 changes: 8 additions & 0 deletions fs/binfmt_flat.c
Original file line number Diff line number Diff line change
Expand Up @@ -820,6 +820,8 @@ static int load_flat_shared_library(int id, struct lib_info *libs)
int res;
char buf[16];

memset(&bprm, 0, sizeof(bprm));

/* Create the file name */
sprintf(buf, "/lib/lib%d.so", id);

Expand All @@ -835,6 +837,12 @@ static int load_flat_shared_library(int id, struct lib_info *libs)
if (!bprm.cred)
goto out;

/* We don't really care about recalculating credentials at this point
* as we're past the point of no return and are dealing with shared
* libraries.
*/
bprm.cred_prepared = 1;

res = prepare_binprm(&bprm);

if (!IS_ERR_VALUE(res))
Expand Down
5 changes: 0 additions & 5 deletions include/linux/capability.h
Original file line number Diff line number Diff line change
Expand Up @@ -417,7 +417,6 @@ extern const kernel_cap_t __cap_init_eff_set;

# define CAP_EMPTY_SET ((kernel_cap_t){{ 0, 0 }})
# define CAP_FULL_SET ((kernel_cap_t){{ ~0, ~0 }})
# define CAP_INIT_EFF_SET ((kernel_cap_t){{ ~CAP_TO_MASK(CAP_SETPCAP), ~0 }})
# define CAP_FS_SET ((kernel_cap_t){{ CAP_FS_MASK_B0 \
| CAP_TO_MASK(CAP_LINUX_IMMUTABLE), \
CAP_FS_MASK_B1 } })
Expand All @@ -427,11 +426,7 @@ extern const kernel_cap_t __cap_init_eff_set;

#endif /* _KERNEL_CAPABILITY_U32S != 2 */

#define CAP_INIT_INH_SET CAP_EMPTY_SET

# define cap_clear(c) do { (c) = __cap_empty_set; } while (0)
# define cap_set_full(c) do { (c) = __cap_full_set; } while (0)
# define cap_set_init_eff(c) do { (c) = __cap_init_eff_set; } while (0)

#define cap_raise(c, flag) ((c).cap[CAP_TO_INDEX(flag)] |= CAP_TO_MASK(flag))
#define cap_lower(c, flag) ((c).cap[CAP_TO_INDEX(flag)] &= ~CAP_TO_MASK(flag))
Expand Down
7 changes: 0 additions & 7 deletions include/linux/init_task.h
Original file line number Diff line number Diff line change
Expand Up @@ -83,13 +83,6 @@ extern struct group_info init_groups;
#define INIT_IDS
#endif

/*
* Because of the reduced scope of CAP_SETPCAP when filesystem
* capabilities are in effect, it is safe to allow CAP_SETPCAP to
* be available in the default configuration.
*/
# define CAP_INIT_BSET CAP_FULL_SET

#ifdef CONFIG_RCU_BOOST
#define INIT_TASK_RCU_BOOST() \
.rcu_boost_mutex = NULL,
Expand Down
13 changes: 13 additions & 0 deletions include/linux/key.h
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,19 @@ static inline key_serial_t key_serial(struct key *key)
return key ? key->serial : 0;
}

/**
* key_is_instantiated - Determine if a key has been positively instantiated
* @key: The key to check.
*
* Return true if the specified key has been positively instantiated, false
* otherwise.
*/
static inline bool key_is_instantiated(const struct key *key)
{
return test_bit(KEY_FLAG_INSTANTIATED, &key->flags) &&
!test_bit(KEY_FLAG_NEGATIVE, &key->flags);
}

#define rcu_dereference_key(KEY) \
(rcu_dereference_protected((KEY)->payload.rcudata, \
rwsem_is_locked(&((struct key *)(KEY))->sem)))
Expand Down
3 changes: 3 additions & 0 deletions include/linux/kmod.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include <linux/errno.h>
#include <linux/compiler.h>
#include <linux/workqueue.h>
#include <linux/sysctl.h>

#define KMOD_PATH_LEN 256

Expand Down Expand Up @@ -109,6 +110,8 @@ call_usermodehelper(char *path, char **argv, char **envp, enum umh_wait wait)
NULL, NULL, NULL);
}

extern struct ctl_table usermodehelper_table[];

extern void usermodehelper_init(void);

extern int usermodehelper_disable(void);
Expand Down
11 changes: 6 additions & 5 deletions include/linux/lsm_audit.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,21 @@
/* Auxiliary data to use in generating the audit record. */
struct common_audit_data {
char type;
#define LSM_AUDIT_DATA_FS 1
#define LSM_AUDIT_DATA_PATH 1
#define LSM_AUDIT_DATA_NET 2
#define LSM_AUDIT_DATA_CAP 3
#define LSM_AUDIT_DATA_IPC 4
#define LSM_AUDIT_DATA_TASK 5
#define LSM_AUDIT_DATA_KEY 6
#define LSM_AUDIT_DATA_NONE 7
#define LSM_AUDIT_DATA_KMOD 8
#define LSM_AUDIT_DATA_INODE 9
#define LSM_AUDIT_DATA_DENTRY 10
struct task_struct *tsk;
union {
struct {
struct path path;
struct inode *inode;
} fs;
struct path path;
struct dentry *dentry;
struct inode *inode;
struct {
int netif;
struct sock *sk;
Expand Down
4 changes: 0 additions & 4 deletions kernel/capability.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,8 @@
*/

const kernel_cap_t __cap_empty_set = CAP_EMPTY_SET;
const kernel_cap_t __cap_full_set = CAP_FULL_SET;
const kernel_cap_t __cap_init_eff_set = CAP_INIT_EFF_SET;

EXPORT_SYMBOL(__cap_empty_set);
EXPORT_SYMBOL(__cap_full_set);
EXPORT_SYMBOL(__cap_init_eff_set);

int file_caps_enabled = 1;

Expand Down
6 changes: 3 additions & 3 deletions kernel/cred.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,10 @@ struct cred init_cred = {
.magic = CRED_MAGIC,
#endif
.securebits = SECUREBITS_DEFAULT,
.cap_inheritable = CAP_INIT_INH_SET,
.cap_inheritable = CAP_EMPTY_SET,
.cap_permitted = CAP_FULL_SET,
.cap_effective = CAP_INIT_EFF_SET,
.cap_bset = CAP_INIT_BSET,
.cap_effective = CAP_FULL_SET,
.cap_bset = CAP_FULL_SET,
.user = INIT_USER,
.user_ns = &init_user_ns,
.group_info = &init_groups,
Expand Down
100 changes: 100 additions & 0 deletions kernel/kmod.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#include <linux/kmod.h>
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/cred.h>
#include <linux/file.h>
#include <linux/fdtable.h>
#include <linux/workqueue.h>
Expand All @@ -43,6 +44,13 @@ extern int max_threads;

static struct workqueue_struct *khelper_wq;

#define CAP_BSET (void *)1
#define CAP_PI (void *)2

static kernel_cap_t usermodehelper_bset = CAP_FULL_SET;
static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET;
static DEFINE_SPINLOCK(umh_sysctl_lock);

#ifdef CONFIG_MODULES

/*
Expand Down Expand Up @@ -132,6 +140,7 @@ EXPORT_SYMBOL(__request_module);
static int ____call_usermodehelper(void *data)
{
struct subprocess_info *sub_info = data;
struct cred *new;
int retval;

spin_lock_irq(&current->sighand->siglock);
Expand All @@ -153,6 +162,19 @@ static int ____call_usermodehelper(void *data)
goto fail;
}

retval = -ENOMEM;
new = prepare_kernel_cred(current);
if (!new)
goto fail;

spin_lock(&umh_sysctl_lock);
new->cap_bset = cap_intersect(usermodehelper_bset, new->cap_bset);
new->cap_inheritable = cap_intersect(usermodehelper_inheritable,
new->cap_inheritable);
spin_unlock(&umh_sysctl_lock);

commit_creds(new);

retval = kernel_execve(sub_info->path,
(const char *const *)sub_info->argv,
(const char *const *)sub_info->envp);
Expand Down Expand Up @@ -420,6 +442,84 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info,
}
EXPORT_SYMBOL(call_usermodehelper_exec);

static int proc_cap_handler(struct ctl_table *table, int write,
void __user *buffer, size_t *lenp, loff_t *ppos)
{
struct ctl_table t;
unsigned long cap_array[_KERNEL_CAPABILITY_U32S];
kernel_cap_t new_cap;
int err, i;

if (write && (!capable(CAP_SETPCAP) ||
!capable(CAP_SYS_MODULE)))
return -EPERM;

/*
* convert from the global kernel_cap_t to the ulong array to print to
* userspace if this is a read.
*/
spin_lock(&umh_sysctl_lock);
for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++) {
if (table->data == CAP_BSET)
cap_array[i] = usermodehelper_bset.cap[i];
else if (table->data == CAP_PI)
cap_array[i] = usermodehelper_inheritable.cap[i];
else
BUG();
}
spin_unlock(&umh_sysctl_lock);

t = *table;
t.data = &cap_array;

/*
* actually read or write and array of ulongs from userspace. Remember
* these are least significant 32 bits first
*/
err = proc_doulongvec_minmax(&t, write, buffer, lenp, ppos);
if (err < 0)
return err;

/*
* convert from the sysctl array of ulongs to the kernel_cap_t
* internal representation
*/
for (i = 0; i < _KERNEL_CAPABILITY_U32S; i++)
new_cap.cap[i] = cap_array[i];

/*
* Drop everything not in the new_cap (but don't add things)
*/
spin_lock(&umh_sysctl_lock);
if (write) {
if (table->data == CAP_BSET)
usermodehelper_bset = cap_intersect(usermodehelper_bset, new_cap);
if (table->data == CAP_PI)
usermodehelper_inheritable = cap_intersect(usermodehelper_inheritable, new_cap);
}
spin_unlock(&umh_sysctl_lock);

return 0;
}

struct ctl_table usermodehelper_table[] = {
{
.procname = "bset",
.data = CAP_BSET,
.maxlen = _KERNEL_CAPABILITY_U32S * sizeof(unsigned long),
.mode = 0600,
.proc_handler = proc_cap_handler,
},
{
.procname = "inheritable",
.data = CAP_PI,
.maxlen = _KERNEL_CAPABILITY_U32S * sizeof(unsigned long),
.mode = 0600,
.proc_handler = proc_cap_handler,
},
{ }
};

void __init usermodehelper_init(void)
{
khelper_wq = create_singlethread_workqueue("khelper");
Expand Down
6 changes: 6 additions & 0 deletions kernel/sysctl.c
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
#include <linux/kprobes.h>
#include <linux/pipe_fs_i.h>
#include <linux/oom.h>
#include <linux/kmod.h>

#include <asm/uaccess.h>
#include <asm/processor.h>
Expand Down Expand Up @@ -615,6 +616,11 @@ static struct ctl_table kern_table[] = {
.mode = 0555,
.child = random_table,
},
{
.procname = "usermodehelper",
.mode = 0555,
.child = usermodehelper_table,
},
{
.procname = "overflowuid",
.data = &overflowuid,
Expand Down
Loading

0 comments on commit b0ca118

Please sign in to comment.