* 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.
#include <linux/init.h>
#include <linux/kernel.h>
-#include <linux/ptrace.h>
+#include <linux/tracehook.h>
#include <linux/errno.h>
#include <linux/sched.h>
#include <linux/security.h>
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
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) {
return __vm_enough_memory(mm, pages, cap_sys_admin);
}
-/**
- * task_tracer_task - return the task that is tracing the given task
- * @task: task to consider
- *
- * Returns NULL if noone is tracing @task, or the &struct task_struct
- * pointer to its tracer.
- *
- * Must be called under rcu_read_lock().
- */
-static struct task_struct *task_tracer_task(struct task_struct *task)
-{
- if (task->ptrace & PT_PTRACED)
- return rcu_dereference(task->parent);
- return NULL;
-}
-
/* binprm security operations */
static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
u32 ptsid = 0;
rcu_read_lock();
- tracer = task_tracer_task(current);
+ tracer = tracehook_tracer_task(current);
if (likely(tracer != NULL)) {
sec = tracer->security;
ptsid = sec->sid;
return dentry_has_perm(current, NULL, dentry, FILE__READ);
}
-static int selinux_inode_permission(struct inode *inode, int mask,
- struct nameidata *nd)
+static int selinux_inode_permission(struct inode *inode, int mask)
{
int rc;
- rc = secondary_ops->inode_permission(inode, mask, nd);
+ rc = secondary_ops->inode_permission(inode, mask);
if (rc)
return rc;
*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)
Otherwise, leave SID unchanged and fail. */
task_lock(p);
rcu_read_lock();
- tracer = task_tracer_task(p);
+ tracer = tracehook_tracer_task(p);
if (tracer != NULL) {
struct task_security_struct *ptsec = tracer->security;
u32 ptsid = ptsec->sid;
.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,
.sem_semctl = selinux_sem_semctl,
.sem_semop = selinux_sem_semop,
- .register_security = selinux_register_security,
-
.d_instantiate = selinux_d_instantiate,
.getprocattr = selinux_getprocattr,
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))
static int __init selinux_nf_ip_init(void)
{
int err = 0;
- u32 iter;
if (!selinux_enabled)
goto out;
printk(KERN_DEBUG "SELinux: Registering netfilter hooks\n");
- for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++) {
- err = nf_register_hook(&selinux_ipv4_ops[iter]);
- if (err)
- panic("SELinux: nf_register_hook for IPv4: error %d\n",
- err);
- }
+ err = nf_register_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
+ if (err)
+ panic("SELinux: nf_register_hooks for IPv4: error %d\n", err);
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++) {
- err = nf_register_hook(&selinux_ipv6_ops[iter]);
- if (err)
- panic("SELinux: nf_register_hook for IPv6: error %d\n",
- err);
- }
+ err = nf_register_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
+ if (err)
+ panic("SELinux: nf_register_hooks for IPv6: error %d\n", err);
#endif /* IPV6 */
out:
#ifdef CONFIG_SECURITY_SELINUX_DISABLE
static void selinux_nf_ip_exit(void)
{
- u32 iter;
-
printk(KERN_DEBUG "SELinux: Unregistering netfilter hooks\n");
- for (iter = 0; iter < ARRAY_SIZE(selinux_ipv4_ops); iter++)
- nf_unregister_hook(&selinux_ipv4_ops[iter]);
+ nf_unregister_hooks(selinux_ipv4_ops, ARRAY_SIZE(selinux_ipv4_ops));
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
- for (iter = 0; iter < ARRAY_SIZE(selinux_ipv6_ops); iter++)
- nf_unregister_hook(&selinux_ipv6_ops[iter]);
+ nf_unregister_hooks(selinux_ipv6_ops, ARRAY_SIZE(selinux_ipv6_ops));
#endif /* IPV6 */
}
#endif