lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <200810021952.GFJ87098.VQFtMOHJOFFLSO@I-love.SAKURA.ne.jp>
Date:	Thu, 2 Oct 2008 19:52:15 +0900
From:	Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>
To:	linux-security-module@...r.kernel.org, linux-kernel@...r.kernel.org
Subject: Re: [PATCH] CRED: ptrace_attach() should use the target process's mutex

Hello.

TOMOYO Linux is now trying to use CRED API, but some troubles were found.
Thus, I want the below patch for TOMOYO Linux.

Regards.
-----
Subject: Add hooks for notifying of start/finish of an execve operation.

This patch adds two hooks, security_start_execve() / security_finish_execve(),
for notifying an LSM module of an execve operation is about to start and
finish.

TOMOYO Linux checks read and/or write permissions at security_dentry_open()
if security_dentry_open() is called outside do_execve() (e.g. sys_open()).
But TOMOYO Linux wants to skip permission checks at security_dentry_open()
if security_dentry_open() is called inside do_execve() (i.e. open_exec()), for
TOMOYO Linux checks permissions at security_bprm_check() using
current->cred->security for program and bprm->cred->security for interpreter.

To implement this exception, I have to tell whether TOMOYO Linux should do
permission checks at security_dentry_open(). And I want a flag that tells
whether the current process is in an execve operation or not.

I tried to use

  static int tmy_dentry_open(struct file *f, const struct cred *cred)
  {
          ...
          /* Don't check read permission here if called from do_execve(). */
          if (mutex_is_locked(&current->cred_exec_mutex))
                  return 0;
          ...
  }

for judging whether the current process is in an execve operation or not.
But it turned out that this code won't work because current->cred_exec_mutex
can be locked by other processes. Thus, I'm trying to use

  struct execve_entry {
         struct list_head list;
         struct task_struct *task;
  };
  
  static LIST_HEAD(execve_list);
  static DEFINE_SPINLOCK(execve_list_lock);
  
  static int tmy_start_execve(void)
  {
          struct execve_entry *ee = kmalloc(sizeof(*ee), GFP_KERNEL);
          if (!ee)
                 return -ENOMEM;
          ee->task = current;
          spin_lock(&execve_list_lock);
          list_add(&ee->list, &execve_list);
          spin_unlock(&execve_list_lock);
          return 0;
  }
  
  static bool tmy_in_execve(void)
  {
          struct task_struct *task = current;
          struct execve_entry *p;
          bool found = false;
          spin_lock(&execve_list_lock);
          list_for_each_entry(p, &execve_list, list) {
                  if (p->task != task)
                          continue;
                  found = true;
                  break;
          }
          spin_unlock(&execve_list_lock);
          return found;
  }
  
  static void tmy_finish_execve(void)
  {
          struct task_struct *task = current;
          struct execve_entry *p;
          struct execve_entry *ee = NULL;
          spin_lock(&execve_list_lock);
          list_for_each_entry(p, &execve_list, list) {
                  if (p->task != task)
                          continue;
                  list_del(&p->list);
                  ee = p;
                  break;
          }
          spin_unlock(&execve_list_lock);
          if (ee)
                 kfree(ee);
  }

and replace mutex_is_locked(&current->cred_exec_mutex) with tmy_in_execve().
To call tmy_start_execve() and tmy_finish_execve(),
I want security_start_execve() / security_finish_execve().

Signed-off-by: Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>
---
 fs/compat.c              |    6 ++++++
 fs/exec.c                |    6 ++++++
 include/linux/security.h |   22 ++++++++++++++++++++++
 security/capability.c    |   11 +++++++++++
 security/security.c      |   10 ++++++++++
 5 files changed, 55 insertions(+)

--- linux-2.6.27-rc7-mm1.orig/fs/compat.c
+++ linux-2.6.27-rc7-mm1/fs/compat.c
@@ -1397,6 +1397,10 @@ int compat_do_execve(char * filename,
 	if (retval < 0)
 		goto out_free;
 
+	retval = security_start_execve();
+	if (retval < 0)
+		goto out_unlock;
+
 	retval = -ENOMEM;
 	bprm->cred = prepare_exec_creds();
 	if (!bprm->cred)
@@ -1448,6 +1452,7 @@ int compat_do_execve(char * filename,
 		goto out;
 
 	/* execve succeeded */
+	security_finish_execve();
 	mutex_unlock(&current->cred_exec_mutex);
 	acct_update_integrals(current);
 	free_bprm(bprm);
@@ -1464,6 +1469,7 @@ out_file:
 	}
 
 out_unlock:
+	security_finish_execve();
 	mutex_unlock(&current->cred_exec_mutex);
 
 out_free:
--- linux-2.6.27-rc7-mm1.orig/fs/exec.c
+++ linux-2.6.27-rc7-mm1/fs/exec.c
@@ -1302,6 +1302,10 @@ int do_execve(char * filename,
 	if (retval < 0)
 		goto out_free;
 
+	retval = security_start_execve();
+	if (retval < 0)
+		goto out_unlock;
+
 	retval = -ENOMEM;
 	bprm->cred = prepare_exec_creds();
 	if (!bprm->cred)
@@ -1354,6 +1358,7 @@ int do_execve(char * filename,
 		goto out;
 
 	/* execve succeeded */
+	security_finish_execve();
 	mutex_unlock(&current->cred_exec_mutex);
 	acct_update_integrals(current);
 	free_bprm(bprm);
@@ -1372,6 +1377,7 @@ out_file:
 	}
 
 out_unlock:
+	security_finish_execve();
 	mutex_unlock(&current->cred_exec_mutex);
 
 out_free:
--- linux-2.6.27-rc7-mm1.orig/include/linux/security.h
+++ linux-2.6.27-rc7-mm1/include/linux/security.h
@@ -192,6 +192,15 @@ static inline void security_free_mnt_opt
  *	on the initial stack to the ELF interpreter to indicate whether libc
  *	should enable secure mode.
  *	@bprm contains the linux_binprm structure.
+ * @start_execve:
+ *	Notify current process of an execve operation is about to start.
+ *	This is called immediately after obtaining current->cred_exec_mutex
+ *	mutex.
+ *	Return 0 if operation was successful.
+ * @finish_execve:
+ *	Notify current process of an execve operation is about to finish.
+ *	This is called immediately before releasing current->cred_exec_mutex
+ *	mutex.
  *
  * Security hooks for filesystem operations.
  *
@@ -1352,6 +1361,8 @@ struct security_operations {
 	int (*settime) (struct timespec *ts, struct timezone *tz);
 	int (*vm_enough_memory) (struct mm_struct *mm, long pages);
 
+	int (*start_execve) (void);
+	void (*finish_execve) (void);
 	int (*bprm_set_creds) (struct linux_binprm *bprm);
 	int (*bprm_check_security) (struct linux_binprm *bprm);
 	int (*bprm_secureexec) (struct linux_binprm *bprm);
@@ -1632,6 +1643,8 @@ int security_syslog(int type);
 int security_settime(struct timespec *ts, struct timezone *tz);
 int security_vm_enough_memory(long pages);
 int security_vm_enough_memory_mm(struct mm_struct *mm, long pages);
+int security_start_execve(void);
+void security_finish_execve(void);
 int security_bprm_set_creds(struct linux_binprm *bprm);
 int security_bprm_check(struct linux_binprm *bprm);
 void security_bprm_committing_creds(struct linux_binprm *bprm);
@@ -1879,6 +1892,15 @@ static inline int security_vm_enough_mem
 	return cap_vm_enough_memory(mm, pages);
 }
 
+static inline int security_start_execve(void)
+{
+	return 0;
+}
+
+static inline void security_finish_execve(void)
+{
+}
+
 static inline int security_bprm_set_creds(struct linux_binprm *bprm)
 {
 	return cap_bprm_set_creds(bprm);
--- linux-2.6.27-rc7-mm1.orig/security/capability.c
+++ linux-2.6.27-rc7-mm1/security/capability.c
@@ -32,6 +32,15 @@ static int cap_quota_on(struct dentry *d
 	return 0;
 }
 
+static int cap_start_execve(void)
+{
+	return 0;
+}
+
+static void cap_finish_execve(void)
+{
+}
+
 static int cap_bprm_check_security (struct linux_binprm *bprm)
 {
 	return 0;
@@ -877,6 +886,8 @@ void security_fixup_ops(struct security_
 	set_to_cap_if_null(ops, syslog);
 	set_to_cap_if_null(ops, settime);
 	set_to_cap_if_null(ops, vm_enough_memory);
+	set_to_cap_if_null(ops, start_execve);
+	set_to_cap_if_null(ops, finish_execve);
 	set_to_cap_if_null(ops, bprm_set_creds);
 	set_to_cap_if_null(ops, bprm_committing_creds);
 	set_to_cap_if_null(ops, bprm_committed_creds);
--- linux-2.6.27-rc7-mm1.orig/security/security.c
+++ linux-2.6.27-rc7-mm1/security/security.c
@@ -199,6 +199,16 @@ int security_vm_enough_memory_mm(struct 
 	return security_ops->vm_enough_memory(mm, pages);
 }
 
+int security_start_execve(void)
+{
+	return security_ops->start_execve();
+}
+
+void security_finish_execve(void)
+{
+	security_ops->finish_execve();
+}
+
 int security_bprm_set_creds(struct linux_binprm *bprm)
 {
 	return security_ops->bprm_set_creds(bprm);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ