|
Subject: [PATCH] new bprm_final_setup patch Newsgroups: gmane.linux.kernel.lsm Date: 2004-12-10 18:21:20 GMT (4 years, 29 weeks, 3 days, 4 hours and 17 minutes ago) A new patch taking in Stephen's comments is attached. This patch defines the bprm_final_setup LSM hook, which is called after apply_creds but with task_lock dropped. This patch is also on a new sourceforge project (sf.net/projects/lsm-stacker) where I'm going to start keeping patches, so that when I don't have to keep sending out 5 patches at a time when I send out stacker. Again, I also attach the relevant parts of selinux/hooks.c. thanks, -serge -- Serge Hallyn <serue <at> us.ibm.com>
Index: linux-2.6.10-stack/fs/exec.c
===================================================================
--- linux-2.6.10-stack.orig/fs/exec.c 2004-12-07 19:35:47.000000000 -0600
+++ linux-2.6.10-stack/fs/exec.c 2004-12-09 13:00:57.000000000 -0600
@@ -953,6 +953,7 @@
unsafe = unsafe_exec(current);
security_bprm_apply_creds(bprm, unsafe);
task_unlock(current);
+ security_bprm_final_setup(bprm);
}
EXPORT_SYMBOL(compute_creds);
Index: linux-2.6.10-stack/include/linux/security.h
===================================================================
--- linux-2.6.10-stack.orig/include/linux/security.h 2004-12-08 18:45:30.000000000 -0600
+++ linux-2.6.10-stack/include/linux/security.h 2004-12-10 10:17:41.000000000 -0600
@@ -115,6 +115,11 @@
* bprm_apply_creds is called under task_lock. @unsafe indicates various
* reasons why it may be unsafe to change security state.
* @bprm contains the linux_binprm structure.
+ * @bprm_final_setup:
+ * Runs after bprm_apply_creds with the task_lock dropped, so that
+ * functions which cannot be called safely under the task_list can
+ * be used.
+ * @bprm contains the linux_binprm structure.
* @bprm_set_security:
* Save security information in the bprm->security field, typically based
* on information about the bprm->file, for later use by the apply_creds
@@ -1041,6 +1046,7 @@
int (*bprm_alloc_security) (struct linux_binprm * bprm);
void (*bprm_free_security) (struct linux_binprm * bprm);
void (*bprm_apply_creds) (struct linux_binprm * bprm, int unsafe);
+ void (*bprm_final_setup) (struct linux_binprm * bprm);
int (*bprm_set_security) (struct linux_binprm * bprm);
int (*bprm_check_security) (struct linux_binprm * bprm);
int (*bprm_secureexec) (struct linux_binprm * bprm);
@@ -1313,6 +1319,10 @@
{
security_ops->bprm_apply_creds (bprm, unsafe);
}
+static inline void security_bprm_final_setup (struct linux_binprm *bprm)
+{
+ security_ops->bprm_final_setup (bprm);
+}
static inline int security_bprm_set (struct linux_binprm *bprm)
{
return security_ops->bprm_set_security (bprm);
@@ -1990,6 +2000,11 @@
cap_bprm_apply_creds (bprm, unsafe);
}
+static inline void security_bprm_final_setup (struct linux_binprm *bprm)
+{
+ return;
+}
+
static inline int security_bprm_set (struct linux_binprm *bprm)
{
return cap_bprm_set_security (bprm);
Index: linux-2.6.10-stack/security/dummy.c
===================================================================
--- linux-2.6.10-stack.orig/security/dummy.c 2004-12-08 18:09:39.000000000 -0600
+++ linux-2.6.10-stack/security/dummy.c 2004-12-09 13:02:21.000000000 -0600
@@ -193,6 +193,11 @@
current->sgid = current->egid = current->fsgid = bprm->e_gid;
}
+static void dummy_bprm_final_setup (struct linux_binprm *bprm)
+{
+ return;
+}
+
static int dummy_bprm_set_security (struct linux_binprm *bprm)
{
return 0;
@@ -908,6 +913,7 @@
set_to_dummy_if_null(ops, bprm_alloc_security);
set_to_dummy_if_null(ops, bprm_free_security);
set_to_dummy_if_null(ops, bprm_apply_creds);
+ set_to_dummy_if_null(ops, bprm_final_setup);
set_to_dummy_if_null(ops, bprm_set_security);
set_to_dummy_if_null(ops, bprm_check_security);
set_to_dummy_if_null(ops, bprm_secureexec);
Index: linux-2.6.10-stack/security/selinux/hooks.c
===================================================================
--- linux-2.6.10-stack.orig/security/selinux/hooks.c 2004-12-08 18:45:29.000000000 -0600
+++ linux-2.6.10-stack/security/selinux/hooks.c 2004-12-10 10:29:58.000000000 -0600
@@ -1807,11 +1807,9 @@
{
struct task_security_struct *tsec;
struct bprm_security_struct *bsec;
- u32 sid;
struct av_decision avd;
- struct itimerval itimer;
- struct rlimit *rlim, *initrlim;
- int rc, i;
+ u32 sid;
+ int rc;
secondary_ops->bprm_apply_creds(bprm, unsafe);
@@ -1821,6 +1819,7 @@
sid = bsec->sid;
tsec->osid = tsec->sid;
+ tsec->unsafe = 0;
if (tsec->sid != sid) {
/* Check for shared state. If not ok, leave SID
unchanged and kill. */
@@ -1829,87 +1828,102 @@
SECCLASS_PROCESS, PROCESS__SHARE,
NULL, &avd);
if (rc) {
- task_unlock(current);
avc_audit(tsec->sid, sid, SECCLASS_PROCESS,
PROCESS__SHARE, &avd, rc, NULL);
- force_sig_specific(SIGKILL, current);
- goto lock_out;
+ tsec->unsafe = 1;
+ return;
}
}
/* Check for ptracing, and update the task SID if ok.
Otherwise, leave SID unchanged and kill. */
if (unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
- rc = avc_has_perm_noaudit(tsec->ptrace_sid, sid,
+ rc = avc_has_perm(tsec->ptrace_sid, sid,
SECCLASS_PROCESS, PROCESS__PTRACE,
- NULL, &avd);
- if (!rc)
- tsec->sid = sid;
- task_unlock(current);
- avc_audit(tsec->ptrace_sid, sid, SECCLASS_PROCESS,
- PROCESS__PTRACE, &avd, rc, NULL);
+ NULL, NULL);
if (rc) {
- force_sig_specific(SIGKILL, current);
- goto lock_out;
+ tsec->unsafe = 1;
+ return;
}
- } else {
- tsec->sid = sid;
- task_unlock(current);
}
- /* Close files for which the new task SID is not authorized. */
- flush_unauthorized_files(current->files);
+ tsec->sid = sid;
+ }
+}
- /* Check whether the new SID can inherit signal state
- from the old SID. If not, clear itimers to avoid
- subsequent signal generation and flush and unblock
- signals. This must occur _after_ the task SID has
- been updated so that any kill done after the flush
- will be checked against the new SID. */
- rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
- PROCESS__SIGINH, NULL, NULL);
- if (rc) {
- memset(&itimer, 0, sizeof itimer);
- for (i = 0; i < 3; i++)
- do_setitimer(i, &itimer, NULL);
- flush_signals(current);
- spin_lock_irq(¤t->sighand->siglock);
- flush_signal_handlers(current, 1);
- sigemptyset(¤t->blocked);
- recalc_sigpending();
- spin_unlock_irq(¤t->sighand->siglock);
- }
+/*
+ * called after apply_creds without the task lock held
+ */
+static void selinux_bprm_final_setup(struct linux_binprm *bprm)
+{
+ struct task_security_struct *tsec;
+ struct bprm_security_struct *bsec;
+ struct rlimit *rlim, *initrlim;
+ struct itimerval itimer;
+ int rc, i;
+ u32 sid;
- /* Check whether the new SID can inherit resource limits
- from the old SID. If not, reset all soft limits to
- the lower of the current task's hard limit and the init
- task's soft limit. Note that the setting of hard limits
- (even to lower them) can be controlled by the setrlimit
- check. The inclusion of the init task's soft limit into
- the computation is to avoid resetting soft limits higher
- than the default soft limit for cases where the default
- is lower than the hard limit, e.g. RLIMIT_CORE or
- RLIMIT_STACK.*/
- rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
- PROCESS__RLIMITINH, NULL, NULL);
- if (rc) {
- for (i = 0; i < RLIM_NLIMITS; i++) {
- rlim = current->signal->rlim + i;
- initrlim = init_task.signal->rlim+i;
- rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
- }
- }
+ tsec = current->security;
+ bsec = bprm->security;
+ sid = bsec->sid;
- /* Wake up the parent if it is waiting so that it can
- recheck wait permission to the new task SID. */
- wake_up_interruptible(¤t->parent->wait_chldexit);
+ if (tsec->unsafe) {
+ force_sig_specific(SIGKILL, current);
+ return;
+ }
-lock_out:
- task_lock(current);
+ if (tsec->osid == tsec->sid)
return;
+
+ /* Close files for which the new task SID is not authorized. */
+ flush_unauthorized_files(current->files);
+
+ /* Check whether the new SID can inherit signal state
+ from the old SID. If not, clear itimers to avoid
+ subsequent signal generation and flush and unblock
+ signals. This must occur _after_ the task SID has
+ been updated so that any kill done after the flush
+ will be checked against the new SID. */
+ rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
+ PROCESS__SIGINH, NULL, NULL);
+ if (rc) {
+ memset(&itimer, 0, sizeof itimer);
+ for (i = 0; i < 3; i++)
+ do_setitimer(i, &itimer, NULL);
+ flush_signals(current);
+ spin_lock_irq(¤t->sighand->siglock);
+ flush_signal_handlers(current, 1);
+ sigemptyset(¤t->blocked);
+ recalc_sigpending();
+ spin_unlock_irq(¤t->sighand->siglock);
+ }
+
+ /* Check whether the new SID can inherit resource limits
+ from the old SID. If not, reset all soft limits to
+ the lower of the current task's hard limit and the init
+ task's soft limit. Note that the setting of hard limits
+ (even to lower them) can be controlled by the setrlimit
+ check. The inclusion of the init task's soft limit into
+ the computation is to avoid resetting soft limits higher
+ than the default soft limit for cases where the default
+ is lower than the hard limit, e.g. RLIMIT_CORE or
+ RLIMIT_STACK.*/
+ rc = avc_has_perm(tsec->osid, tsec->sid, SECCLASS_PROCESS,
+ PROCESS__RLIMITINH, NULL, NULL);
+ if (rc) {
+ for (i = 0; i < RLIM_NLIMITS; i++) {
+ rlim = current->signal->rlim + i;
+ initrlim = init_task.signal->rlim+i;
+ rlim->rlim_cur = min(rlim->rlim_max,initrlim->rlim_cur);
+ }
}
+
+ /* Wake up the parent if it is waiting so that it can
+ recheck wait permission to the new task SID. */
+ wake_up_interruptible(¤t->parent->wait_chldexit);
}
+
/* superblock security operations */
static int selinux_sb_alloc_security(struct super_block *sb)
@@ -4180,6 +4194,7 @@
.bprm_alloc_security = selinux_bprm_alloc_security,
.bprm_free_security = selinux_bprm_free_security,
.bprm_apply_creds = selinux_bprm_apply_creds,
+ .bprm_final_setup = selinux_bprm_final_setup,
.bprm_set_security = selinux_bprm_set_security,
.bprm_check_security = selinux_bprm_check_security,
.bprm_secureexec = selinux_bprm_secureexec,
Index: linux-2.6.10-stack/security/selinux/include/objsec.h
===================================================================
--- linux-2.6.10-stack.orig/security/selinux/include/objsec.h 2004-12-07 19:35:54.000000000 -0600
+++ linux-2.6.10-stack/security/selinux/include/objsec.h 2004-12-09 17:19:48.000000000 -0600
@@ -35,6 +35,12 @@
u32 create_sid; /* fscreate SID */
struct avc_entry_ref avcr; /* reference to process permissions */
u32 ptrace_sid; /* SID of ptrace parent */
+
+ /*
+ * used to share failure information from bprm_apply_creds()
+ * to bprm_final_setup().
+ */
+ char unsafe;
};
struct inode_security_struct {
|
|
|