提交 847106ff 编写于 作者: L Linus Torvalds

Merge branch 'for-linus' of...

Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/security-testing-2.6: (25 commits)
  security: remove register_security hook
  security: remove dummy module fix
  security: remove dummy module
  security: remove unused sb_get_mnt_opts hook
  LSM/SELinux: show LSM mount options in /proc/mounts
  SELinux: allow fstype unknown to policy to use xattrs if present
  security: fix return of void-valued expressions
  SELinux: use do_each_thread as a proper do/while block
  SELinux: remove unused and shadowed addrlen variable
  SELinux: more user friendly unknown handling printk
  selinux: change handling of invalid classes (Was: Re: 2.6.26-rc5-mm1 selinux whine)
  SELinux: drop load_mutex in security_load_policy
  SELinux: fix off by 1 reference of class_to_string in context_struct_compute_av
  SELinux: open code sidtab lock
  SELinux: open code load_mutex
  SELinux: open code policy_rwlock
  selinux: fix endianness bug in network node address handling
  selinux: simplify ioctl checking
  SELinux: enable processes with mac_admin to get the raw inode contexts
  Security: split proc ptrace checking into read vs. attach
  ...
......@@ -750,7 +750,7 @@ struct proc_fs_info {
const char *str;
};
static void show_sb_opts(struct seq_file *m, struct super_block *sb)
static int show_sb_opts(struct seq_file *m, struct super_block *sb)
{
static const struct proc_fs_info fs_info[] = {
{ MS_SYNCHRONOUS, ",sync" },
......@@ -764,6 +764,8 @@ static void show_sb_opts(struct seq_file *m, struct super_block *sb)
if (sb->s_flags & fs_infop->flag)
seq_puts(m, fs_infop->str);
}
return security_sb_show_options(m, sb);
}
static void show_mnt_opts(struct seq_file *m, struct vfsmount *mnt)
......@@ -806,11 +808,14 @@ static int show_vfsmnt(struct seq_file *m, void *v)
seq_putc(m, ' ');
show_type(m, mnt->mnt_sb);
seq_puts(m, __mnt_is_readonly(mnt) ? " ro" : " rw");
show_sb_opts(m, mnt->mnt_sb);
err = show_sb_opts(m, mnt->mnt_sb);
if (err)
goto out;
show_mnt_opts(m, mnt);
if (mnt->mnt_sb->s_op->show_options)
err = mnt->mnt_sb->s_op->show_options(m, mnt);
seq_puts(m, " 0 0\n");
out:
return err;
}
......@@ -865,10 +870,13 @@ static int show_mountinfo(struct seq_file *m, void *v)
seq_putc(m, ' ');
mangle(m, mnt->mnt_devname ? mnt->mnt_devname : "none");
seq_puts(m, sb->s_flags & MS_RDONLY ? " ro" : " rw");
show_sb_opts(m, sb);
err = show_sb_opts(m, sb);
if (err)
goto out;
if (sb->s_op->show_options)
err = sb->s_op->show_options(m, mnt);
seq_putc(m, '\n');
out:
return err;
}
......
......@@ -233,7 +233,7 @@ static int check_mem_permission(struct task_struct *task)
*/
if (task->parent == current && (task->ptrace & PT_PTRACED) &&
task_is_stopped_or_traced(task) &&
ptrace_may_attach(task))
ptrace_may_access(task, PTRACE_MODE_ATTACH))
return 0;
/*
......@@ -251,7 +251,8 @@ struct mm_struct *mm_for_maps(struct task_struct *task)
task_lock(task);
if (task->mm != mm)
goto out;
if (task->mm != current->mm && __ptrace_may_attach(task) < 0)
if (task->mm != current->mm &&
__ptrace_may_access(task, PTRACE_MODE_READ) < 0)
goto out;
task_unlock(task);
return mm;
......@@ -518,7 +519,7 @@ static int proc_fd_access_allowed(struct inode *inode)
*/
task = get_proc_task(inode);
if (task) {
allowed = ptrace_may_attach(task);
allowed = ptrace_may_access(task, PTRACE_MODE_READ);
put_task_struct(task);
}
return allowed;
......@@ -904,7 +905,7 @@ static ssize_t environ_read(struct file *file, char __user *buf,
if (!task)
goto out_no_task;
if (!ptrace_may_attach(task))
if (!ptrace_may_access(task, PTRACE_MODE_READ))
goto out;
ret = -ENOMEM;
......
......@@ -210,7 +210,7 @@ static int show_map(struct seq_file *m, void *v)
dev_t dev = 0;
int len;
if (maps_protect && !ptrace_may_attach(task))
if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
return -EACCES;
if (file) {
......@@ -646,7 +646,7 @@ static ssize_t pagemap_read(struct file *file, char __user *buf,
goto out;
ret = -EACCES;
if (!ptrace_may_attach(task))
if (!ptrace_may_access(task, PTRACE_MODE_READ))
goto out_task;
ret = -EINVAL;
......@@ -747,7 +747,7 @@ static int show_numa_map_checked(struct seq_file *m, void *v)
struct proc_maps_private *priv = m->private;
struct task_struct *task = priv->task;
if (maps_protect && !ptrace_may_attach(task))
if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
return -EACCES;
return show_numa_map(m, v);
......
......@@ -113,7 +113,7 @@ static int show_map(struct seq_file *m, void *_vml)
struct proc_maps_private *priv = m->private;
struct task_struct *task = priv->task;
if (maps_protect && !ptrace_may_attach(task))
if (maps_protect && !ptrace_may_access(task, PTRACE_MODE_READ))
return -EACCES;
return nommu_vma_show(m, vml->vma);
......
......@@ -95,8 +95,12 @@ extern void __ptrace_link(struct task_struct *child,
struct task_struct *new_parent);
extern void __ptrace_unlink(struct task_struct *child);
extern void ptrace_untrace(struct task_struct *child);
extern int ptrace_may_attach(struct task_struct *task);
extern int __ptrace_may_attach(struct task_struct *task);
#define PTRACE_MODE_READ 1
#define PTRACE_MODE_ATTACH 2
/* Returns 0 on success, -errno on denial. */
extern int __ptrace_may_access(struct task_struct *task, unsigned int mode);
/* Returns true on success, false on denial. */
extern bool ptrace_may_access(struct task_struct *task, unsigned int mode);
static inline int ptrace_reparented(struct task_struct *child)
{
......
......@@ -46,7 +46,8 @@ struct audit_krule;
*/
extern int cap_capable(struct task_struct *tsk, int cap);
extern int cap_settime(struct timespec *ts, struct timezone *tz);
extern int cap_ptrace(struct task_struct *parent, struct task_struct *child);
extern int cap_ptrace(struct task_struct *parent, struct task_struct *child,
unsigned int mode);
extern int cap_capget(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
extern int cap_capset_check(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
extern void cap_capset_set(struct task_struct *target, kernel_cap_t *effective, kernel_cap_t *inheritable, kernel_cap_t *permitted);
......@@ -79,6 +80,7 @@ struct xfrm_selector;
struct xfrm_policy;
struct xfrm_state;
struct xfrm_user_sec_ctx;
struct seq_file;
extern int cap_netlink_send(struct sock *sk, struct sk_buff *skb);
extern int cap_netlink_recv(struct sk_buff *skb, int cap);
......@@ -289,10 +291,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* Update module state after a successful pivot.
* @old_path contains the path for the old root.
* @new_path contains the path for the new root.
* @sb_get_mnt_opts:
* Get the security relevant mount options used for a superblock
* @sb the superblock to get security mount options from
* @opts binary data structure containing all lsm mount data
* @sb_set_mnt_opts:
* Set the security relevant mount options used for a superblock
* @sb the superblock to set security mount options for
......@@ -1170,6 +1168,7 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* attributes would be changed by the execve.
* @parent contains the task_struct structure for parent process.
* @child contains the task_struct structure for child process.
* @mode contains the PTRACE_MODE flags indicating the form of access.
* Return 0 if permission is granted.
* @capget:
* Get the @effective, @inheritable, and @permitted capability sets for
......@@ -1240,11 +1239,6 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
* @pages contains the number of pages.
* Return 0 if permission is granted.
*
* @register_security:
* allow module stacking.
* @name contains the name of the security module being stacked.
* @ops contains a pointer to the struct security_operations of the module to stack.
*
* @secid_to_secctx:
* Convert secid to security context.
* @secid contains the security ID.
......@@ -1295,7 +1289,8 @@ static inline void security_free_mnt_opts(struct security_mnt_opts *opts)
struct security_operations {
char name[SECURITY_NAME_MAX + 1];
int (*ptrace) (struct task_struct *parent, struct task_struct *child);
int (*ptrace) (struct task_struct *parent, struct task_struct *child,
unsigned int mode);
int (*capget) (struct task_struct *target,
kernel_cap_t *effective,
kernel_cap_t *inheritable, kernel_cap_t *permitted);
......@@ -1328,6 +1323,7 @@ struct security_operations {
void (*sb_free_security) (struct super_block *sb);
int (*sb_copy_data) (char *orig, char *copy);
int (*sb_kern_mount) (struct super_block *sb, void *data);
int (*sb_show_options) (struct seq_file *m, struct super_block *sb);
int (*sb_statfs) (struct dentry *dentry);
int (*sb_mount) (char *dev_name, struct path *path,
char *type, unsigned long flags, void *data);
......@@ -1343,8 +1339,6 @@ struct security_operations {
struct path *new_path);
void (*sb_post_pivotroot) (struct path *old_path,
struct path *new_path);
int (*sb_get_mnt_opts) (const struct super_block *sb,
struct security_mnt_opts *opts);
int (*sb_set_mnt_opts) (struct super_block *sb,
struct security_mnt_opts *opts);
void (*sb_clone_mnt_opts) (const struct super_block *oldsb,
......@@ -1472,10 +1466,6 @@ struct security_operations {
int (*netlink_send) (struct sock *sk, struct sk_buff *skb);
int (*netlink_recv) (struct sk_buff *skb, int cap);
/* allow module stacking */
int (*register_security) (const char *name,
struct security_operations *ops);
void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
int (*getprocattr) (struct task_struct *p, char *name, char **value);
......@@ -1565,7 +1555,6 @@ struct security_operations {
extern int security_init(void);
extern int security_module_enable(struct security_operations *ops);
extern int register_security(struct security_operations *ops);
extern int mod_reg_security(const char *name, struct security_operations *ops);
extern struct dentry *securityfs_create_file(const char *name, mode_t mode,
struct dentry *parent, void *data,
const struct file_operations *fops);
......@@ -1573,7 +1562,8 @@ extern struct dentry *securityfs_create_dir(const char *name, struct dentry *par
extern void securityfs_remove(struct dentry *dentry);
/* Security operations */
int security_ptrace(struct task_struct *parent, struct task_struct *child);
int security_ptrace(struct task_struct *parent, struct task_struct *child,
unsigned int mode);
int security_capget(struct task_struct *target,
kernel_cap_t *effective,
kernel_cap_t *inheritable,
......@@ -1606,6 +1596,7 @@ int security_sb_alloc(struct super_block *sb);
void security_sb_free(struct super_block *sb);
int security_sb_copy_data(char *orig, char *copy);
int security_sb_kern_mount(struct super_block *sb, void *data);
int security_sb_show_options(struct seq_file *m, struct super_block *sb);
int security_sb_statfs(struct dentry *dentry);
int security_sb_mount(char *dev_name, struct path *path,
char *type, unsigned long flags, void *data);
......@@ -1617,8 +1608,6 @@ void security_sb_post_remount(struct vfsmount *mnt, unsigned long flags, void *d
void security_sb_post_addmount(struct vfsmount *mnt, struct path *mountpoint);
int security_sb_pivotroot(struct path *old_path, struct path *new_path);
void security_sb_post_pivotroot(struct path *old_path, struct path *new_path);
int security_sb_get_mnt_opts(const struct super_block *sb,
struct security_mnt_opts *opts);
int security_sb_set_mnt_opts(struct super_block *sb, struct security_mnt_opts *opts);
void security_sb_clone_mnt_opts(const struct super_block *oldsb,
struct super_block *newsb);
......@@ -1755,9 +1744,11 @@ static inline int security_init(void)
return 0;
}
static inline int security_ptrace(struct task_struct *parent, struct task_struct *child)
static inline int security_ptrace(struct task_struct *parent,
struct task_struct *child,
unsigned int mode)
{
return cap_ptrace(parent, child);
return cap_ptrace(parent, child, mode);
}
static inline int security_capget(struct task_struct *target,
......@@ -1881,6 +1872,12 @@ static inline int security_sb_kern_mount(struct super_block *sb, void *data)
return 0;
}
static inline int security_sb_show_options(struct seq_file *m,
struct super_block *sb)
{
return 0;
}
static inline int security_sb_statfs(struct dentry *dentry)
{
return 0;
......@@ -1927,12 +1924,6 @@ static inline int security_sb_pivotroot(struct path *old_path,
static inline void security_sb_post_pivotroot(struct path *old_path,
struct path *new_path)
{ }
static inline int security_sb_get_mnt_opts(const struct super_block *sb,
struct security_mnt_opts *opts)
{
security_init_mnt_opts(opts);
return 0;
}
static inline int security_sb_set_mnt_opts(struct super_block *sb,
struct security_mnt_opts *opts)
......
......@@ -121,7 +121,7 @@ int ptrace_check_attach(struct task_struct *child, int kill)
return ret;
}
int __ptrace_may_attach(struct task_struct *task)
int __ptrace_may_access(struct task_struct *task, unsigned int mode)
{
/* May we inspect the given task?
* This check is used both for attaching with ptrace
......@@ -148,16 +148,16 @@ int __ptrace_may_attach(struct task_struct *task)
if (!dumpable && !capable(CAP_SYS_PTRACE))
return -EPERM;
return security_ptrace(current, task);
return security_ptrace(current, task, mode);
}
int ptrace_may_attach(struct task_struct *task)
bool ptrace_may_access(struct task_struct *task, unsigned int mode)
{
int err;
task_lock(task);
err = __ptrace_may_attach(task);
err = __ptrace_may_access(task, mode);
task_unlock(task);
return !err;
return (!err ? true : false);
}
int ptrace_attach(struct task_struct *task)
......@@ -195,7 +195,7 @@ int ptrace_attach(struct task_struct *task)
/* the same process cannot be attached many times */
if (task->ptrace & PT_PTRACED)
goto bad;
retval = __ptrace_may_attach(task);
retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH);
if (retval)
goto bad;
......@@ -494,7 +494,8 @@ int ptrace_traceme(void)
*/
task_lock(current);
if (!(current->ptrace & PT_PTRACED)) {
ret = security_ptrace(current->parent, current);
ret = security_ptrace(current->parent, current,
PTRACE_MODE_ATTACH);
/*
* Set the ptrace bit in the process ptrace flags.
*/
......
......@@ -73,17 +73,9 @@ config SECURITY_NETWORK_XFRM
IPSec.
If you are unsure how to answer this question, answer N.
config SECURITY_CAPABILITIES
bool "Default Linux Capabilities"
depends on SECURITY
default y
help
This enables the "default" Linux capabilities functionality.
If you are unsure how to answer this question, answer Y.
config SECURITY_FILE_CAPABILITIES
bool "File POSIX Capabilities (EXPERIMENTAL)"
depends on (SECURITY=n || SECURITY_CAPABILITIES!=n) && EXPERIMENTAL
depends on EXPERIMENTAL
default n
help
This enables filesystem capabilities, allowing you to give
......
......@@ -6,16 +6,13 @@ obj-$(CONFIG_KEYS) += keys/
subdir-$(CONFIG_SECURITY_SELINUX) += selinux
subdir-$(CONFIG_SECURITY_SMACK) += smack
# if we don't select a security model, use the default capabilities
ifneq ($(CONFIG_SECURITY),y)
# always enable default capabilities
obj-y += commoncap.o
endif
# Object file lists
obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o
obj-$(CONFIG_SECURITY) += security.o capability.o inode.o
# Must precede capability.o in order to stack properly.
obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
obj-$(CONFIG_SECURITY_SMACK) += commoncap.o smack/built-in.o
obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += commoncap.o root_plug.o
obj-$(CONFIG_SECURITY_SMACK) += smack/built-in.o
obj-$(CONFIG_SECURITY_ROOTPLUG) += root_plug.o
obj-$(CONFIG_CGROUP_DEVICE) += device_cgroup.o
此差异已折叠。
......@@ -63,7 +63,8 @@ int cap_settime(struct timespec *ts, struct timezone *tz)
return 0;
}
int cap_ptrace (struct task_struct *parent, struct task_struct *child)
int cap_ptrace (struct task_struct *parent, struct task_struct *child,
unsigned int mode)
{
/* Derived from arch/i386/kernel/ptrace.c:sys_ptrace. */
if (!cap_issubset(child->cap_permitted, parent->cap_permitted) &&
......
此差异已折叠。
......@@ -28,9 +28,6 @@
#include <linux/usb.h>
#include <linux/moduleparam.h>
/* flag to keep track of how we were registered */
static int secondary;
/* default is a generic type of usb to serial converter */
static int vendor_id = 0x0557;
static int product_id = 0x2008;
......@@ -97,13 +94,7 @@ static int __init rootplug_init (void)
if (register_security (&rootplug_security_ops)) {
printk (KERN_INFO
"Failure registering Root Plug module with the kernel\n");
/* try registering with primary module */
if (mod_reg_security (MY_NAME, &rootplug_security_ops)) {
printk (KERN_INFO "Failure registering Root Plug "
" module with primary security module.\n");
return -EINVAL;
}
secondary = 1;
}
printk (KERN_INFO "Root Plug module initialized, "
"vendor_id = %4.4x, product id = %4.4x\n", vendor_id, product_id);
......
......@@ -20,8 +20,8 @@
/* Boot-time LSM user choice */
static __initdata char chosen_lsm[SECURITY_NAME_MAX + 1];
/* things that live in dummy.c */
extern struct security_operations dummy_security_ops;
/* things that live in capability.c */
extern struct security_operations default_security_ops;
extern void security_fixup_ops(struct security_operations *ops);
struct security_operations *security_ops; /* Initialized to NULL */
......@@ -57,13 +57,8 @@ int __init security_init(void)
{
printk(KERN_INFO "Security Framework initialized\n");
if (verify(&dummy_security_ops)) {
printk(KERN_ERR "%s could not verify "
"dummy_security_ops structure.\n", __func__);
return -EIO;
}
security_ops = &dummy_security_ops;
security_fixup_ops(&default_security_ops);
security_ops = &default_security_ops;
do_security_initcalls();
return 0;
......@@ -122,7 +117,7 @@ int register_security(struct security_operations *ops)
return -EINVAL;
}
if (security_ops != &dummy_security_ops)
if (security_ops != &default_security_ops)
return -EAGAIN;
security_ops = ops;
......@@ -130,40 +125,12 @@ int register_security(struct security_operations *ops)
return 0;
}
/**
* mod_reg_security - allows security modules to be "stacked"
* @name: a pointer to a string with the name of the security_options to be registered
* @ops: a pointer to the struct security_options that is to be registered
*
* This function allows security modules to be stacked if the currently loaded
* security module allows this to happen. It passes the @name and @ops to the
* register_security function of the currently loaded security module.
*
* The return value depends on the currently loaded security module, with 0 as
* success.
*/
int mod_reg_security(const char *name, struct security_operations *ops)
{
if (verify(ops)) {
printk(KERN_INFO "%s could not verify "
"security operations.\n", __func__);
return -EINVAL;
}
if (ops == security_ops) {
printk(KERN_INFO "%s security operations "
"already registered.\n", __func__);
return -EINVAL;
}
return security_ops->register_security(name, ops);
}
/* Security operations */
int security_ptrace(struct task_struct *parent, struct task_struct *child)
int security_ptrace(struct task_struct *parent, struct task_struct *child,
unsigned int mode)
{
return security_ops->ptrace(parent, child);
return security_ops->ptrace(parent, child, mode);
}
int security_capget(struct task_struct *target,
......@@ -291,6 +258,11 @@ int security_sb_kern_mount(struct super_block *sb, void *data)
return security_ops->sb_kern_mount(sb, data);
}
int security_sb_show_options(struct seq_file *m, struct super_block *sb)
{
return security_ops->sb_show_options(m, sb);
}
int security_sb_statfs(struct dentry *dentry)
{
return security_ops->sb_statfs(dentry);
......@@ -342,12 +314,6 @@ void security_sb_post_pivotroot(struct path *old_path, struct path *new_path)
security_ops->sb_post_pivotroot(old_path, new_path);
}
int security_sb_get_mnt_opts(const struct super_block *sb,
struct security_mnt_opts *opts)
{
return security_ops->sb_get_mnt_opts(sb, opts);
}
int security_sb_set_mnt_opts(struct super_block *sb,
struct security_mnt_opts *opts)
{
......@@ -894,7 +860,7 @@ EXPORT_SYMBOL(security_secctx_to_secid);
void security_release_secctx(char *secdata, u32 seclen)
{
return security_ops->release_secctx(secdata, seclen);
security_ops->release_secctx(secdata, seclen);
}
EXPORT_SYMBOL(security_release_secctx);
......@@ -1011,12 +977,12 @@ int security_sk_alloc(struct sock *sk, int family, gfp_t priority)
void security_sk_free(struct sock *sk)
{
return security_ops->sk_free_security(sk);
security_ops->sk_free_security(sk);
}
void security_sk_clone(const struct sock *sk, struct sock *newsk)
{
return security_ops->sk_clone_security(sk, newsk);
security_ops->sk_clone_security(sk, newsk);
}
void security_sk_classify_flow(struct sock *sk, struct flowi *fl)
......
......@@ -9,7 +9,8 @@
* James Morris <jmorris@redhat.com>
*
* Copyright (C) 2001,2002 Networks Associates Technology, Inc.
* Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
* Copyright (C) 2003-2008 Red Hat, Inc., James Morris <jmorris@redhat.com>
* Eric Paris <eparis@redhat.com>
* Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
* <dgoeddel@trustedcs.com>
* Copyright (C) 2006, 2007 Hewlett-Packard Development Company, L.P.
......@@ -42,9 +43,7 @@
#include <linux/fdtable.h>
#include <linux/namei.h>
#include <linux/mount.h>
#include <linux/ext2_fs.h>
#include <linux/proc_fs.h>
#include <linux/kd.h>
#include <linux/netfilter_ipv4.h>
#include <linux/netfilter_ipv6.h>
#include <linux/tty.h>
......@@ -53,7 +52,7 @@
#include <net/tcp.h> /* struct or_callable used in sock_rcv_skb */
#include <net/net_namespace.h>
#include <net/netlabel.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
#include <asm/ioctls.h>
#include <asm/atomic.h>
#include <linux/bitops.h>
......@@ -104,7 +103,9 @@ int selinux_enforcing;
static int __init enforcing_setup(char *str)
{
selinux_enforcing = simple_strtol(str, NULL, 0);
unsigned long enforcing;
if (!strict_strtoul(str, 0, &enforcing))
selinux_enforcing = enforcing ? 1 : 0;
return 1;
}
__setup("enforcing=", enforcing_setup);
......@@ -115,7 +116,9 @@ int selinux_enabled = CONFIG_SECURITY_SELINUX_BOOTPARAM_VALUE;
static int __init selinux_enabled_setup(char *str)
{
selinux_enabled = simple_strtol(str, NULL, 0);
unsigned long enabled;
if (!strict_strtoul(str, 0, &enabled))
selinux_enabled = enabled ? 1 : 0;
return 1;
}
__setup("selinux=", selinux_enabled_setup);
......@@ -123,13 +126,11 @@ __setup("selinux=", selinux_enabled_setup);
int selinux_enabled = 1;
#endif
/* Original (dummy) security module. */
static struct security_operations *original_ops;
/* Minimal support for a secondary security module,
just to allow the use of the dummy or capability modules.
The owlsm module can alternatively be used as a secondary
module as long as CONFIG_OWLSM_FD is not enabled. */
/*
* Minimal support for a secondary security module,
* just to allow the use of the capability module.
*/
static struct security_operations *secondary_ops;
/* Lists of inode and superblock security structures initialized
......@@ -554,13 +555,15 @@ static int selinux_set_mnt_opts(struct super_block *sb,
struct task_security_struct *tsec = current->security;
struct superblock_security_struct *sbsec = sb->s_security;
const char *name = sb->s_type->name;
struct inode *inode = sbsec->sb->s_root->d_inode;
struct inode_security_struct *root_isec = inode->i_security;
struct dentry *root = sb->s_root;
struct inode *root_inode = root->d_inode;
struct inode_security_struct *root_isec = root_inode->i_security;
u32 fscontext_sid = 0, context_sid = 0, rootcontext_sid = 0;
u32 defcontext_sid = 0;
char **mount_options = opts->mnt_opts;
int *flags = opts->mnt_opts_flags;
int num_opts = opts->num_mnt_opts;
bool can_xattr = false;
mutex_lock(&sbsec->lock);
......@@ -594,7 +597,7 @@ static int selinux_set_mnt_opts(struct super_block *sb,
*/
if (sbsec->initialized && (sb->s_type->fs_flags & FS_BINARY_MOUNTDATA)
&& (num_opts == 0))
goto out;
goto out;
/*
* parse the mount options, check if they are valid sids.
......@@ -664,14 +667,24 @@ static int selinux_set_mnt_opts(struct super_block *sb,
goto out;
}
if (strcmp(sb->s_type->name, "proc") == 0)
if (strcmp(name, "proc") == 0)
sbsec->proc = 1;
/*
* test if the fs supports xattrs, fs_use might make use of this if the
* fs has no definition in policy.
*/
if (root_inode->i_op->getxattr) {
rc = root_inode->i_op->getxattr(root, XATTR_NAME_SELINUX, NULL, 0);
if (rc >= 0 || rc == -ENODATA)
can_xattr = true;
}
/* Determine the labeling behavior to use for this filesystem type. */
rc = security_fs_use(sb->s_type->name, &sbsec->behavior, &sbsec->sid);
rc = security_fs_use(name, &sbsec->behavior, &sbsec->sid, can_xattr);
if (rc) {
printk(KERN_WARNING "%s: security_fs_use(%s) returned %d\n",
__func__, sb->s_type->name, rc);
__func__, name, rc);
goto out;
}
......@@ -956,6 +969,57 @@ static int superblock_doinit(struct super_block *sb, void *data)
return rc;
}
void selinux_write_opts(struct seq_file *m, struct security_mnt_opts *opts)
{
int i;
char *prefix;
for (i = 0; i < opts->num_mnt_opts; i++) {
char *has_comma = strchr(opts->mnt_opts[i], ',');
switch (opts->mnt_opts_flags[i]) {
case CONTEXT_MNT:
prefix = CONTEXT_STR;
break;
case FSCONTEXT_MNT:
prefix = FSCONTEXT_STR;
break;
case ROOTCONTEXT_MNT:
prefix = ROOTCONTEXT_STR;
break;
case DEFCONTEXT_MNT:
prefix = DEFCONTEXT_STR;
break;
default:
BUG();
};
/* we need a comma before each option */
seq_putc(m, ',');
seq_puts(m, prefix);
if (has_comma)
seq_putc(m, '\"');
seq_puts(m, opts->mnt_opts[i]);
if (has_comma)
seq_putc(m, '\"');
}
}
static int selinux_sb_show_options(struct seq_file *m, struct super_block *sb)
{
struct security_mnt_opts opts;
int rc;
rc = selinux_get_mnt_opts(sb, &opts);
if (rc)
return rc;
selinux_write_opts(m, &opts);
security_free_mnt_opts(&opts);
return rc;
}
static inline u16 inode_mode_to_security_class(umode_t mode)
{
switch (mode & S_IFMT) {
......@@ -1682,14 +1746,23 @@ static inline u32 file_to_av(struct file *file)
/* Hook functions begin here. */
static int selinux_ptrace(struct task_struct *parent, struct task_struct *child)
static int selinux_ptrace(struct task_struct *parent,
struct task_struct *child,
unsigned int mode)
{
int rc;
rc = secondary_ops->ptrace(parent, child);
rc = secondary_ops->ptrace(parent, child, mode);
if (rc)
return rc;
if (mode == PTRACE_MODE_READ) {
struct task_security_struct *tsec = parent->security;
struct task_security_struct *csec = child->security;
return avc_has_perm(tsec->sid, csec->sid,
SECCLASS_FILE, FILE__READ, NULL);
}
return task_has_perm(parent, child, PROCESS__PTRACE);
}
......@@ -2495,7 +2568,7 @@ static int selinux_inode_init_security(struct inode *inode, struct inode *dir,
}
if (value && len) {
rc = security_sid_to_context(newsid, &context, &clen);
rc = security_sid_to_context_force(newsid, &context, &clen);
if (rc) {
kfree(namep);
return rc;
......@@ -2669,6 +2742,11 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
return rc;
rc = security_context_to_sid(value, size, &newsid);
if (rc == -EINVAL) {
if (!capable(CAP_MAC_ADMIN))
return rc;
rc = security_context_to_sid_force(value, size, &newsid);
}
if (rc)
return rc;
......@@ -2690,7 +2768,7 @@ static int selinux_inode_setxattr(struct dentry *dentry, const char *name,
}
static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
const void *value, size_t size,
const void *value, size_t size,
int flags)
{
struct inode *inode = dentry->d_inode;
......@@ -2703,10 +2781,11 @@ static void selinux_inode_post_setxattr(struct dentry *dentry, const char *name,
return;
}
rc = security_context_to_sid(value, size, &newsid);
rc = security_context_to_sid_force(value, size, &newsid);
if (rc) {
printk(KERN_WARNING "%s: unable to obtain SID for context "
"%s, rc=%d\n", __func__, (char *)value, -rc);
printk(KERN_ERR "SELinux: unable to map context to SID"
"for (%s, %lu), rc=%d\n",
inode->i_sb->s_id, inode->i_ino, -rc);
return;
}
......@@ -2735,9 +2814,7 @@ static int selinux_inode_removexattr(struct dentry *dentry, const char *name)
}
/*
* Copy the in-core inode security context value to the user. If the
* getxattr() prior to this succeeded, check to see if we need to
* canonicalize the value to be finally returned to the user.
* Copy the inode security context value to the user.
*
* Permission check is handled by selinux_inode_getxattr hook.
*/
......@@ -2746,12 +2823,33 @@ static int selinux_inode_getsecurity(const struct inode *inode, const char *name
u32 size;
int error;
char *context = NULL;
struct task_security_struct *tsec = current->security;
struct inode_security_struct *isec = inode->i_security;
if (strcmp(name, XATTR_SELINUX_SUFFIX))
return -EOPNOTSUPP;
error = security_sid_to_context(isec->sid, &context, &size);
/*
* If the caller has CAP_MAC_ADMIN, then get the raw context
* value even if it is not defined by current policy; otherwise,
* use the in-core value under current policy.
* Use the non-auditing forms of the permission checks since
* getxattr may be called by unprivileged processes commonly
* and lack of permission just means that we fall back to the
* in-core context value, not a denial.
*/
error = secondary_ops->capable(current, CAP_MAC_ADMIN);
if (!error)
error = avc_has_perm_noaudit(tsec->sid, tsec->sid,
SECCLASS_CAPABILITY2,
CAPABILITY2__MAC_ADMIN,
0,
NULL);
if (!error)
error = security_sid_to_context_force(isec->sid, &context,
&size);
else
error = security_sid_to_context(isec->sid, &context, &size);
if (error)
return error;
error = size;
......@@ -2865,46 +2963,16 @@ static void selinux_file_free_security(struct file *file)
static int selinux_file_ioctl(struct file *file, unsigned int cmd,
unsigned long arg)
{
int error = 0;
switch (cmd) {
case FIONREAD:
/* fall through */
case FIBMAP:
/* fall through */
case FIGETBSZ:
/* fall through */
case EXT2_IOC_GETFLAGS:
/* fall through */
case EXT2_IOC_GETVERSION:
error = file_has_perm(current, file, FILE__GETATTR);
break;
case EXT2_IOC_SETFLAGS:
/* fall through */
case EXT2_IOC_SETVERSION:
error = file_has_perm(current, file, FILE__SETATTR);
break;
/* sys_ioctl() checks */
case FIONBIO:
/* fall through */
case FIOASYNC:
error = file_has_perm(current, file, 0);
break;
u32 av = 0;
case KDSKBENT:
case KDSKBSENT:
error = task_has_capability(current, CAP_SYS_TTY_CONFIG);
break;
if (_IOC_DIR(cmd) & _IOC_WRITE)
av |= FILE__WRITE;
if (_IOC_DIR(cmd) & _IOC_READ)
av |= FILE__READ;
if (!av)
av = FILE__IOCTL;
/* default case assumes that the command will go
* to the file's ioctl() function.
*/
default:
error = file_has_perm(current, file, FILE__IOCTL);
}
return error;
return file_has_perm(current, file, av);
}
static int file_map_prot_check(struct file *file, unsigned long prot, int shared)
......@@ -3663,7 +3731,7 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
struct sockaddr_in6 *addr6 = NULL;
unsigned short snum;
struct sock *sk = sock->sk;
u32 sid, node_perm, addrlen;
u32 sid, node_perm;
tsec = current->security;
isec = SOCK_INODE(sock)->i_security;
......@@ -3671,12 +3739,10 @@ static int selinux_socket_bind(struct socket *sock, struct sockaddr *address, in
if (family == PF_INET) {
addr4 = (struct sockaddr_in *)address;
snum = ntohs(addr4->sin_port);
addrlen = sizeof(addr4->sin_addr.s_addr);
addrp = (char *)&addr4->sin_addr.s_addr;
} else {
addr6 = (struct sockaddr_in6 *)address;
snum = ntohs(addr6->sin6_port);
addrlen = sizeof(addr6->sin6_addr.s6_addr);
addrp = (char *)&addr6->sin6_addr.s6_addr;
}
......@@ -5047,24 +5113,6 @@ static void selinux_ipc_getsecid(struct kern_ipc_perm *ipcp, u32 *secid)
*secid = isec->sid;
}
/* module stacking operations */
static int selinux_register_security(const char *name, struct security_operations *ops)
{
if (secondary_ops != original_ops) {
printk(KERN_ERR "%s: There is already a secondary security "
"module registered.\n", __func__);
return -EINVAL;
}
secondary_ops = ops;
printk(KERN_INFO "%s: Registering secondary module %s\n",
__func__,
name);
return 0;
}
static void selinux_d_instantiate(struct dentry *dentry, struct inode *inode)
{
if (inode)
......@@ -5153,6 +5201,12 @@ static int selinux_setprocattr(struct task_struct *p,
size--;
}
error = security_context_to_sid(value, size, &sid);
if (error == -EINVAL && !strcmp(name, "fscreate")) {
if (!capable(CAP_MAC_ADMIN))
return error;
error = security_context_to_sid_force(value, size,
&sid);
}
if (error)
return error;
}
......@@ -5186,12 +5240,12 @@ static int selinux_setprocattr(struct task_struct *p,
struct task_struct *g, *t;
struct mm_struct *mm = p->mm;
read_lock(&tasklist_lock);
do_each_thread(g, t)
do_each_thread(g, t) {
if (t->mm == mm && t != p) {
read_unlock(&tasklist_lock);
return -EPERM;
}
while_each_thread(g, t);
} while_each_thread(g, t);
read_unlock(&tasklist_lock);
}
......@@ -5343,10 +5397,10 @@ static struct security_operations selinux_ops = {
.sb_free_security = selinux_sb_free_security,
.sb_copy_data = selinux_sb_copy_data,
.sb_kern_mount = selinux_sb_kern_mount,
.sb_show_options = selinux_sb_show_options,
.sb_statfs = selinux_sb_statfs,
.sb_mount = selinux_mount,
.sb_umount = selinux_umount,
.sb_get_mnt_opts = selinux_get_mnt_opts,
.sb_set_mnt_opts = selinux_set_mnt_opts,
.sb_clone_mnt_opts = selinux_sb_clone_mnt_opts,
.sb_parse_opts_str = selinux_parse_opts_str,
......@@ -5378,7 +5432,7 @@ static struct security_operations selinux_ops = {
.inode_listsecurity = selinux_inode_listsecurity,
.inode_need_killpriv = selinux_inode_need_killpriv,
.inode_killpriv = selinux_inode_killpriv,
.inode_getsecid = selinux_inode_getsecid,
.inode_getsecid = selinux_inode_getsecid,
.file_permission = selinux_file_permission,
.file_alloc_security = selinux_file_alloc_security,
......@@ -5419,7 +5473,7 @@ static struct security_operations selinux_ops = {
.task_to_inode = selinux_task_to_inode,
.ipc_permission = selinux_ipc_permission,
.ipc_getsecid = selinux_ipc_getsecid,
.ipc_getsecid = selinux_ipc_getsecid,
.msg_msg_alloc_security = selinux_msg_msg_alloc_security,
.msg_msg_free_security = selinux_msg_msg_free_security,
......@@ -5443,8 +5497,6 @@ static struct security_operations selinux_ops = {
.sem_semctl = selinux_sem_semctl,
.sem_semop = selinux_sem_semop,
.register_security = selinux_register_security,
.d_instantiate = selinux_d_instantiate,
.getprocattr = selinux_getprocattr,
......@@ -5538,7 +5590,7 @@ static __init int selinux_init(void)
0, SLAB_PANIC, NULL);
avc_init();
original_ops = secondary_ops = security_ops;
secondary_ops = security_ops;
if (!secondary_ops)
panic("SELinux: No initial security operations\n");
if (register_security(&selinux_ops))
......
/*
* SELinux support for the Audit LSM hooks
*
* Most of below header was moved from include/linux/selinux.h which
* Most of below header was moved from include/linux/selinux.h which
* is released under below copyrights:
*
* Author: James Morris <jmorris@redhat.com>
......@@ -52,7 +52,7 @@ void selinux_audit_rule_free(void *rule);
* -errno on failure.
*/
int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *rule,
struct audit_context *actx);
struct audit_context *actx);
/**
* selinux_audit_rule_known - check to see if rule contains selinux fields.
......
......@@ -75,13 +75,12 @@ struct avc_audit_data {
/* Initialize an AVC audit data structure. */
#define AVC_AUDIT_DATA_INIT(_d,_t) \
{ memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; }
{ memset((_d), 0, sizeof(struct avc_audit_data)); (_d)->type = AVC_AUDIT_DATA_##_t; }
/*
* AVC statistics
*/
struct avc_cache_stats
{
struct avc_cache_stats {
unsigned int lookups;
unsigned int hits;
unsigned int misses;
......@@ -97,8 +96,8 @@ struct avc_cache_stats
void __init avc_init(void);
void avc_audit(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct av_decision *avd, int result, struct avc_audit_data *auditdata);
u16 tclass, u32 requested,
struct av_decision *avd, int result, struct avc_audit_data *auditdata);
#define AVC_STRICT 1 /* Ignore permissive mode. */
int avc_has_perm_noaudit(u32 ssid, u32 tsid,
......@@ -107,8 +106,8 @@ int avc_has_perm_noaudit(u32 ssid, u32 tsid,
struct av_decision *avd);
int avc_has_perm(u32 ssid, u32 tsid,
u16 tclass, u32 requested,
struct avc_audit_data *auditdata);
u16 tclass, u32 requested,
struct avc_audit_data *auditdata);
u32 avc_policy_seqno(void);
......@@ -122,7 +121,7 @@ u32 avc_policy_seqno(void);
#define AVC_CALLBACK_AUDITDENY_DISABLE 128
int avc_add_callback(int (*callback)(u32 event, u32 ssid, u32 tsid,
u16 tclass, u32 perms,
u16 tclass, u32 perms,
u32 *out_retained),
u32 events, u32 ssid, u32 tsid,
u16 tclass, u32 perms);
......
......@@ -44,7 +44,6 @@ struct inode_security_struct {
u16 sclass; /* security class of this object */
unsigned char initialized; /* initialization flag */
struct mutex lock;
unsigned char inherit; /* inherit SID from parent entry */
};
struct file_security_struct {
......
......@@ -93,12 +93,17 @@ int security_change_sid(u32 ssid, u32 tsid,
int security_sid_to_context(u32 sid, char **scontext,
u32 *scontext_len);
int security_sid_to_context_force(u32 sid, char **scontext, u32 *scontext_len);
int security_context_to_sid(const char *scontext, u32 scontext_len,
u32 *out_sid);
int security_context_to_sid_default(const char *scontext, u32 scontext_len,
u32 *out_sid, u32 def_sid, gfp_t gfp_flags);
int security_context_to_sid_force(const char *scontext, u32 scontext_len,
u32 *sid);
int security_get_user_sids(u32 callsid, char *username,
u32 **sids, u32 *nel);
......@@ -131,7 +136,7 @@ int security_get_allow_unknown(void);
#define SECURITY_FS_USE_MNTPOINT 6 /* use mountpoint labeling */
int security_fs_use(const char *fstype, unsigned int *behavior,
u32 *sid);
u32 *sid, bool can_xattr);
int security_genfs_sid(const char *fstype, char *name, u16 sclass,
u32 *sid);
......
......@@ -38,7 +38,6 @@
#include <linux/ipv6.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <asm/bug.h>
#include "netnode.h"
#include "objsec.h"
......
......@@ -37,7 +37,6 @@
#include <linux/ipv6.h>
#include <net/ip.h>
#include <net/ipv6.h>
#include <asm/bug.h>
#include "netport.h"
#include "objsec.h"
......@@ -272,7 +271,7 @@ static __init int sel_netport_init(void)
}
ret = avc_add_callback(sel_netport_avc_callback, AVC_CALLBACK_RESET,
SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
SECSID_NULL, SECSID_NULL, SECCLASS_NULL, 0);
if (ret != 0)
panic("avc_add_callback() failed, error %d\n", ret);
......
......@@ -27,7 +27,7 @@
#include <linux/seq_file.h>
#include <linux/percpu.h>
#include <linux/audit.h>
#include <asm/uaccess.h>
#include <linux/uaccess.h>
/* selinuxfs pseudo filesystem for exporting the security policy API.
Based on the proc code and the fs/nfsd/nfsctl.c code. */
......@@ -57,14 +57,18 @@ int selinux_compat_net = SELINUX_COMPAT_NET_VALUE;
static int __init checkreqprot_setup(char *str)
{
selinux_checkreqprot = simple_strtoul(str, NULL, 0) ? 1 : 0;
unsigned long checkreqprot;
if (!strict_strtoul(str, 0, &checkreqprot))
selinux_checkreqprot = checkreqprot ? 1 : 0;
return 1;
}
__setup("checkreqprot=", checkreqprot_setup);
static int __init selinux_compat_net_setup(char *str)
{
selinux_compat_net = simple_strtoul(str, NULL, 0) ? 1 : 0;
unsigned long compat_net;
if (!strict_strtoul(str, 0, &compat_net))
selinux_compat_net = compat_net ? 1 : 0;
return 1;
}
__setup("selinux_compat_net=", selinux_compat_net_setup);
......@@ -352,11 +356,6 @@ static ssize_t sel_write_load(struct file *file, const char __user *buf,
length = count;
out1:
printk(KERN_INFO "SELinux: policy loaded with handle_unknown=%s\n",
(security_get_reject_unknown() ? "reject" :
(security_get_allow_unknown() ? "allow" : "deny")));
audit_log(current->audit_context, GFP_KERNEL, AUDIT_MAC_POLICY_LOAD,
"policy loaded auid=%u ses=%u",
audit_get_loginuid(current),
......
......@@ -311,7 +311,7 @@ void avtab_hash_eval(struct avtab *h, char *tag)
}
printk(KERN_DEBUG "SELinux: %s: %d entries and %d/%d buckets used, "
"longest chain length %d sum of chain length^2 %Lu\n",
"longest chain length %d sum of chain length^2 %llu\n",
tag, h->nel, slots_used, h->nslot, max_chain_len,
chain2_len_sum);
}
......
......@@ -28,6 +28,8 @@ struct context {
u32 role;
u32 type;
struct mls_range range;
char *str; /* string representation if context cannot be mapped. */
u32 len; /* length of string in bytes */
};
static inline void mls_context_init(struct context *c)
......@@ -106,20 +108,43 @@ static inline void context_init(struct context *c)
static inline int context_cpy(struct context *dst, struct context *src)
{
int rc;
dst->user = src->user;
dst->role = src->role;
dst->type = src->type;
return mls_context_cpy(dst, src);
if (src->str) {
dst->str = kstrdup(src->str, GFP_ATOMIC);
if (!dst->str)
return -ENOMEM;
dst->len = src->len;
} else {
dst->str = NULL;
dst->len = 0;
}
rc = mls_context_cpy(dst, src);
if (rc) {
kfree(dst->str);
return rc;
}
return 0;
}
static inline void context_destroy(struct context *c)
{
c->user = c->role = c->type = 0;
kfree(c->str);
c->str = NULL;
c->len = 0;
mls_context_destroy(c);
}
static inline int context_cmp(struct context *c1, struct context *c2)
{
if (c1->len && c2->len)
return (c1->len == c2->len && !strcmp(c1->str, c2->str));
if (c1->len || c2->len)
return 0;
return ((c1->user == c2->user) &&
(c1->role == c2->role) &&
(c1->type == c2->type) &&
......
......@@ -239,7 +239,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c)
* Policy read-lock must be held for sidtab lookup.
*
*/
int mls_context_to_sid(char oldc,
int mls_context_to_sid(struct policydb *pol,
char oldc,
char **scontext,
struct context *context,
struct sidtab *s,
......@@ -286,7 +287,7 @@ int mls_context_to_sid(char oldc,
*p++ = 0;
for (l = 0; l < 2; l++) {
levdatum = hashtab_search(policydb.p_levels.table, scontextp);
levdatum = hashtab_search(pol->p_levels.table, scontextp);
if (!levdatum) {
rc = -EINVAL;
goto out;
......@@ -311,7 +312,7 @@ int mls_context_to_sid(char oldc,
*rngptr++ = 0;
}
catdatum = hashtab_search(policydb.p_cats.table,
catdatum = hashtab_search(pol->p_cats.table,
scontextp);
if (!catdatum) {
rc = -EINVAL;
......@@ -327,7 +328,7 @@ int mls_context_to_sid(char oldc,
if (rngptr) {
int i;
rngdatum = hashtab_search(policydb.p_cats.table, rngptr);
rngdatum = hashtab_search(pol->p_cats.table, rngptr);
if (!rngdatum) {
rc = -EINVAL;
goto out;
......@@ -395,7 +396,7 @@ int mls_from_string(char *str, struct context *context, gfp_t gfp_mask)
if (!tmpstr) {
rc = -ENOMEM;
} else {
rc = mls_context_to_sid(':', &tmpstr, context,
rc = mls_context_to_sid(&policydb, ':', &tmpstr, context,
NULL, SECSID_NULL);
kfree(freestr);
}
......@@ -436,13 +437,13 @@ int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
struct mls_level *usercon_clr = &(usercon->range.level[1]);
/* Honor the user's default level if we can */
if (mls_level_between(user_def, fromcon_sen, fromcon_clr)) {
if (mls_level_between(user_def, fromcon_sen, fromcon_clr))
*usercon_sen = *user_def;
} else if (mls_level_between(fromcon_sen, user_def, user_clr)) {
else if (mls_level_between(fromcon_sen, user_def, user_clr))
*usercon_sen = *fromcon_sen;
} else if (mls_level_between(fromcon_clr, user_low, user_def)) {
else if (mls_level_between(fromcon_clr, user_low, user_def))
*usercon_sen = *user_low;
} else
else
return -EINVAL;
/* Lower the clearance of available contexts
......
......@@ -30,7 +30,8 @@ int mls_context_isvalid(struct policydb *p, struct context *c);
int mls_range_isvalid(struct policydb *p, struct mls_range *r);
int mls_level_isvalid(struct policydb *p, struct mls_level *l);
int mls_context_to_sid(char oldc,
int mls_context_to_sid(struct policydb *p,
char oldc,
char **scontext,
struct context *context,
struct sidtab *s,
......
......@@ -1478,7 +1478,8 @@ int policydb_read(struct policydb *p, void *fp)
struct ocontext *l, *c, *newc;
struct genfs *genfs_p, *genfs, *newgenfs;
int i, j, rc;
__le32 buf[8];
__le32 buf[4];
u32 nodebuf[8];
u32 len, len2, config, nprim, nel, nel2;
char *policydb_str;
struct policydb_compat_info *info;
......@@ -1749,11 +1750,11 @@ int policydb_read(struct policydb *p, void *fp)
goto bad;
break;
case OCON_NODE:
rc = next_entry(buf, fp, sizeof(u32) * 2);
rc = next_entry(nodebuf, fp, sizeof(u32) * 2);
if (rc < 0)
goto bad;
c->u.node.addr = le32_to_cpu(buf[0]);
c->u.node.mask = le32_to_cpu(buf[1]);
c->u.node.addr = nodebuf[0]; /* network order */
c->u.node.mask = nodebuf[1]; /* network order */
rc = context_read_and_validate(&c->context[0], p, fp);
if (rc)
goto bad;
......@@ -1782,13 +1783,13 @@ int policydb_read(struct policydb *p, void *fp)
case OCON_NODE6: {
int k;
rc = next_entry(buf, fp, sizeof(u32) * 8);
rc = next_entry(nodebuf, fp, sizeof(u32) * 8);
if (rc < 0)
goto bad;
for (k = 0; k < 4; k++)
c->u.node6.addr[k] = le32_to_cpu(buf[k]);
c->u.node6.addr[k] = nodebuf[k];
for (k = 0; k < 4; k++)
c->u.node6.mask[k] = le32_to_cpu(buf[k+4]);
c->u.node6.mask[k] = nodebuf[k+4];
if (context_read_and_validate(&c->context[0], p, fp))
goto bad;
break;
......
此差异已折叠。
......@@ -14,10 +14,6 @@
#define SIDTAB_HASH(sid) \
(sid & SIDTAB_HASH_MASK)
#define INIT_SIDTAB_LOCK(s) spin_lock_init(&s->lock)
#define SIDTAB_LOCK(s, x) spin_lock_irqsave(&s->lock, x)
#define SIDTAB_UNLOCK(s, x) spin_unlock_irqrestore(&s->lock, x)
int sidtab_init(struct sidtab *s)
{
int i;
......@@ -30,7 +26,7 @@ int sidtab_init(struct sidtab *s)
s->nel = 0;
s->next_sid = 1;
s->shutdown = 0;
INIT_SIDTAB_LOCK(s);
spin_lock_init(&s->lock);
return 0;
}
......@@ -86,7 +82,7 @@ int sidtab_insert(struct sidtab *s, u32 sid, struct context *context)
return rc;
}
struct context *sidtab_search(struct sidtab *s, u32 sid)
static struct context *sidtab_search_core(struct sidtab *s, u32 sid, int force)
{
int hvalue;
struct sidtab_node *cur;
......@@ -99,7 +95,10 @@ struct context *sidtab_search(struct sidtab *s, u32 sid)
while (cur != NULL && sid > cur->sid)
cur = cur->next;
if (cur == NULL || sid != cur->sid) {
if (force && cur && sid == cur->sid && cur->context.len)
return &cur->context;
if (cur == NULL || sid != cur->sid || cur->context.len) {
/* Remap invalid SIDs to the unlabeled SID. */
sid = SECINITSID_UNLABELED;
hvalue = SIDTAB_HASH(sid);
......@@ -113,6 +112,16 @@ struct context *sidtab_search(struct sidtab *s, u32 sid)
return &cur->context;
}
struct context *sidtab_search(struct sidtab *s, u32 sid)
{
return sidtab_search_core(s, sid, 0);
}
struct context *sidtab_search_force(struct sidtab *s, u32 sid)
{
return sidtab_search_core(s, sid, 1);
}
int sidtab_map(struct sidtab *s,
int (*apply) (u32 sid,
struct context *context,
......@@ -138,43 +147,6 @@ int sidtab_map(struct sidtab *s,
return rc;
}
void sidtab_map_remove_on_error(struct sidtab *s,
int (*apply) (u32 sid,
struct context *context,
void *args),
void *args)
{
int i, ret;
struct sidtab_node *last, *cur, *temp;
if (!s)
return;
for (i = 0; i < SIDTAB_SIZE; i++) {
last = NULL;
cur = s->htable[i];
while (cur != NULL) {
ret = apply(cur->sid, &cur->context, args);
if (ret) {
if (last)
last->next = cur->next;
else
s->htable[i] = cur->next;
temp = cur;
cur = cur->next;
context_destroy(&temp->context);
kfree(temp);
s->nel--;
} else {
last = cur;
cur = cur->next;
}
}
}
return;
}
static inline u32 sidtab_search_context(struct sidtab *s,
struct context *context)
{
......@@ -204,7 +176,7 @@ int sidtab_context_to_sid(struct sidtab *s,
sid = sidtab_search_context(s, context);
if (!sid) {
SIDTAB_LOCK(s, flags);
spin_lock_irqsave(&s->lock, flags);
/* Rescan now that we hold the lock. */
sid = sidtab_search_context(s, context);
if (sid)
......@@ -215,11 +187,15 @@ int sidtab_context_to_sid(struct sidtab *s,
goto unlock_out;
}
sid = s->next_sid++;
if (context->len)
printk(KERN_INFO
"SELinux: Context %s is not valid (left unmapped).\n",
context->str);
ret = sidtab_insert(s, sid, context);
if (ret)
s->next_sid--;
unlock_out:
SIDTAB_UNLOCK(s, flags);
spin_unlock_irqrestore(&s->lock, flags);
}
if (ret)
......@@ -284,19 +260,19 @@ void sidtab_set(struct sidtab *dst, struct sidtab *src)
{
unsigned long flags;
SIDTAB_LOCK(src, flags);
spin_lock_irqsave(&src->lock, flags);
dst->htable = src->htable;
dst->nel = src->nel;
dst->next_sid = src->next_sid;
dst->shutdown = 0;
SIDTAB_UNLOCK(src, flags);
spin_unlock_irqrestore(&src->lock, flags);
}
void sidtab_shutdown(struct sidtab *s)
{
unsigned long flags;
SIDTAB_LOCK(s, flags);
spin_lock_irqsave(&s->lock, flags);
s->shutdown = 1;
SIDTAB_UNLOCK(s, flags);
spin_unlock_irqrestore(&s->lock, flags);
}
......@@ -32,6 +32,7 @@ struct sidtab {
int sidtab_init(struct sidtab *s);
int sidtab_insert(struct sidtab *s, u32 sid, struct context *context);
struct context *sidtab_search(struct sidtab *s, u32 sid);
struct context *sidtab_search_force(struct sidtab *s, u32 sid);
int sidtab_map(struct sidtab *s,
int (*apply) (u32 sid,
......@@ -39,12 +40,6 @@ int sidtab_map(struct sidtab *s,
void *args),
void *args);
void sidtab_map_remove_on_error(struct sidtab *s,
int (*apply) (u32 sid,
struct context *context,
void *args),
void *args);
int sidtab_context_to_sid(struct sidtab *s,
struct context *context,
u32 *sid);
......
......@@ -95,11 +95,12 @@ struct inode_smack *new_inode_smack(char *smack)
*
* Do the capability checks, and require read and write.
*/
static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp)
static int smack_ptrace(struct task_struct *ptp, struct task_struct *ctp,
unsigned int mode)
{
int rc;
rc = cap_ptrace(ptp, ctp);
rc = cap_ptrace(ptp, ctp, mode);
if (rc != 0)
return rc;
......@@ -1821,27 +1822,6 @@ static void smack_ipc_getsecid(struct kern_ipc_perm *ipp, u32 *secid)
*secid = smack_to_secid(smack);
}
/* module stacking operations */
/**
* smack_register_security - stack capability module
* @name: module name
* @ops: module operations - ignored
*
* Allow the capability module to register.
*/
static int smack_register_security(const char *name,
struct security_operations *ops)
{
if (strcmp(name, "capability") != 0)
return -EINVAL;
printk(KERN_INFO "%s: Registering secondary module %s\n",
__func__, name);
return 0;
}
/**
* smack_d_instantiate - Make sure the blob is correct on an inode
* @opt_dentry: unused
......@@ -2672,8 +2652,6 @@ struct security_operations smack_ops = {
.netlink_send = cap_netlink_send,
.netlink_recv = cap_netlink_recv,
.register_security = smack_register_security,
.d_instantiate = smack_d_instantiate,
.getprocattr = smack_getprocattr,
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册