Commit 081bb1e6 authored by Andrew Morton's avatar Andrew Morton Committed by Linus Torvalds

[PATCH] Rework SELinux binprm hooks

From: Stephen Smalley <sds@epoch.ncsc.mil>

This patch reworks the SELinux binprm hook functions to use a security
structure for the linux_binprm rather than directly stuffing the security
identifier into the void* security field.  It also performs some cleanup of
the SELinux binprm hook functions, and one miscellaneous fix.
parent 2a1c7412
...@@ -1332,31 +1332,19 @@ static int selinux_netlink_recv(struct sk_buff *skb) ...@@ -1332,31 +1332,19 @@ static int selinux_netlink_recv(struct sk_buff *skb)
static int selinux_bprm_alloc_security(struct linux_binprm *bprm) static int selinux_bprm_alloc_security(struct linux_binprm *bprm)
{ {
int rc; struct bprm_security_struct *bsec;
/* Make sure that the secondary module doesn't use the bsec = kmalloc(sizeof(struct bprm_security_struct), GFP_KERNEL);
bprm->security field, since we do not yet support chaining if (!bsec)
of multiple security structures on the field. Neither return -ENOMEM;
the dummy nor the capability module use the field. The owlsm
module uses the field if CONFIG_OWLSM_FD is enabled. */ memset(bsec, 0, sizeof *bsec);
rc = secondary_ops->bprm_alloc_security(bprm); bsec->magic = SELINUX_MAGIC;
if (rc) bsec->bprm = bprm;
return rc; bsec->sid = SECINITSID_UNLABELED;
if (bprm->security) { bsec->set = 0;
printk(KERN_WARNING "%s: no support yet for chaining on the "
"security field by secondary modules.\n", __FUNCTION__); bprm->security = bsec;
/* Release the secondary module's security object. */
secondary_ops->bprm_free_security(bprm);
/* Unregister the secondary module to prevent problems
with subsequent binprm hooks. This will revert to the
original (dummy) module for the secondary operations. */
rc = security_ops->unregister_security("unknown", secondary_ops);
if (rc)
return rc;
printk(KERN_WARNING "%s: Unregistered the secondary security "
"module.\n", __FUNCTION__);
}
bprm->security = NULL;
return 0; return 0;
} }
...@@ -1365,6 +1353,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) ...@@ -1365,6 +1353,7 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
struct task_security_struct *tsec; struct task_security_struct *tsec;
struct inode *inode = bprm->file->f_dentry->d_inode; struct inode *inode = bprm->file->f_dentry->d_inode;
struct inode_security_struct *isec; struct inode_security_struct *isec;
struct bprm_security_struct *bsec;
u32 newsid; u32 newsid;
struct avc_audit_data ad; struct avc_audit_data ad;
int rc; int rc;
...@@ -1373,15 +1362,16 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) ...@@ -1373,15 +1362,16 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
if (rc) if (rc)
return rc; return rc;
if (bprm->sh_bang || bprm->security) bsec = bprm->security;
/* The security field should already be set properly. */
if (bsec->set)
return 0; return 0;
tsec = current->security; tsec = current->security;
isec = inode->i_security; isec = inode->i_security;
/* Default to the current task SID. */ /* Default to the current task SID. */
bprm->security = (void *)tsec->sid; bsec->sid = tsec->sid;
/* Reset create SID on execve. */ /* Reset create SID on execve. */
tsec->create_sid = 0; tsec->create_sid = 0;
...@@ -1427,9 +1417,10 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm) ...@@ -1427,9 +1417,10 @@ static int selinux_bprm_set_security(struct linux_binprm *bprm)
return rc; return rc;
/* Set the security field to the new SID. */ /* Set the security field to the new SID. */
bprm->security = (void*) newsid; bsec->sid = newsid;
} }
bsec->set = 1;
return 0; return 0;
} }
...@@ -1463,8 +1454,9 @@ static int selinux_bprm_secureexec (struct linux_binprm *bprm) ...@@ -1463,8 +1454,9 @@ static int selinux_bprm_secureexec (struct linux_binprm *bprm)
static void selinux_bprm_free_security(struct linux_binprm *bprm) static void selinux_bprm_free_security(struct linux_binprm *bprm)
{ {
/* Nothing to do - not dynamically allocated. */ struct bprm_security_struct *bsec = bprm->security;
return; bprm->security = NULL;
kfree(bsec);
} }
/* Derived from fs/exec.c:flush_old_files. */ /* Derived from fs/exec.c:flush_old_files. */
...@@ -1509,6 +1501,7 @@ static inline void flush_unauthorized_files(struct files_struct * files) ...@@ -1509,6 +1501,7 @@ static inline void flush_unauthorized_files(struct files_struct * files)
static void selinux_bprm_compute_creds(struct linux_binprm *bprm) static void selinux_bprm_compute_creds(struct linux_binprm *bprm)
{ {
struct task_security_struct *tsec, *psec; struct task_security_struct *tsec, *psec;
struct bprm_security_struct *bsec;
u32 sid; u32 sid;
struct av_decision avd; struct av_decision avd;
int rc; int rc;
...@@ -1517,9 +1510,8 @@ static void selinux_bprm_compute_creds(struct linux_binprm *bprm) ...@@ -1517,9 +1510,8 @@ static void selinux_bprm_compute_creds(struct linux_binprm *bprm)
tsec = current->security; tsec = current->security;
sid = (u32)bprm->security; bsec = bprm->security;
if (!sid) sid = bsec->sid;
sid = tsec->sid;
tsec->osid = tsec->sid; tsec->osid = tsec->sid;
if (tsec->sid != sid) { if (tsec->sid != sid) {
...@@ -3114,9 +3106,8 @@ static int selinux_getprocattr(struct task_struct *p, ...@@ -3114,9 +3106,8 @@ static int selinux_getprocattr(struct task_struct *p,
char *name, void *value, size_t size) char *name, void *value, size_t size)
{ {
struct task_security_struct *tsec; struct task_security_struct *tsec;
u32 sid; u32 sid, len;
char *context; char *context;
size_t len;
int error; int error;
if (current != p) { if (current != p) {
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include <linux/list.h> #include <linux/list.h>
#include <linux/sched.h> #include <linux/sched.h>
#include <linux/fs.h> #include <linux/fs.h>
#include <linux/binfmts.h>
#include <linux/in.h> #include <linux/in.h>
#include "flask.h" #include "flask.h"
#include "avc.h" #include "avc.h"
...@@ -85,6 +86,13 @@ struct ipc_security_struct { ...@@ -85,6 +86,13 @@ struct ipc_security_struct {
struct avc_entry_ref avcr; /* reference to permissions */ struct avc_entry_ref avcr; /* reference to permissions */
}; };
struct bprm_security_struct {
unsigned long magic; /* magic number for this module */
struct linux_binprm *bprm; /* back pointer to bprm object */
u32 sid; /* SID for transformed process */
unsigned char set;
};
extern int inode_security_set_sid(struct inode *inode, u32 sid); extern int inode_security_set_sid(struct inode *inode, u32 sid);
#endif /* _SELINUX_OBJSEC_H_ */ #endif /* _SELINUX_OBJSEC_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment