public inbox for linux-audit@redhat.com
 help / color / mirror / Atom feed
* audit-ptrace patch (untested)
@ 2007-03-05 14:50 Alexander Viro
  2007-03-06 14:46 ` Stephen Smalley
  0 siblings, 1 reply; 13+ messages in thread
From: Alexander Viro @ 2007-03-05 14:50 UTC (permalink / raw)
  To: linux-audit

That one is on top of security_getprocattr() patch.  See bz#228384...

diff --git a/include/linux/audit.h b/include/linux/audit.h
index 229fa01..cce8b6c 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -90,6 +90,7 @@
 #define AUDIT_MQ_GETSETATTR	1315	/* POSIX MQ get/set attribute record type */
 #define AUDIT_KERNEL_OTHER	1316	/* For use by 3rd party modules */
 #define AUDIT_FD_PAIR		1317    /* audit record for pipe/socketpair */
+#define AUDIT_OBJ_PID	1318	/* ptrace target */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -351,6 +352,8 @@ extern void __audit_inode(const char *name, const struct inode *inode);
 extern void __audit_inode_child(const char *dname, const struct inode *inode,
 				const struct inode *parent);
 extern void __audit_inode_update(const struct inode *inode);
+extern void __audit_ptrace(struct task_struct *t);
+
 static inline int audit_dummy_context(void)
 {
 	void *p = current->audit_context;
@@ -376,6 +379,12 @@ static inline void audit_inode_update(const struct inode *inode) {
 		__audit_inode_update(inode);
 }
 
+static inline void audit_ptrace(struct task_struct *t)
+{
+	if (unlikely(!audit_dummy_context()))
+		__audit_ptrace(t);
+}
+
 				/* Private API (for audit.c only) */
 extern unsigned int audit_serial(void);
 extern void auditsc_get_stamp(struct audit_context *ctx,
@@ -476,6 +485,7 @@ extern int audit_n_rules;
 #define audit_mq_timedreceive(d,l,p,t) ({ 0; })
 #define audit_mq_notify(d,n) ({ 0; })
 #define audit_mq_getsetattr(d,s) ({ 0; })
+#define audit_ptrace(t) ((void)0)
 #define audit_n_rules 0
 #endif
 
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 89875b2..c8465ea 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -209,6 +209,9 @@ struct audit_context {
 	unsigned long	    personality;
 	int		    arch;
 
+	pid_t		    target_pid;
+	char *		    obj_ctx;
+
 #if AUDIT_DEBUG
 	int		    put_count;
 	int		    ino_count;
@@ -729,6 +732,7 @@ static inline void audit_free_context(struct audit_context *context)
 		audit_free_names(context);
 		audit_free_aux(context);
 		kfree(context->filterkey);
+		kfree(context->obj_ctx);
 		kfree(context);
 		context  = previous;
 	} while (context);
@@ -967,6 +971,13 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 		audit_log_end(ab);
 	}
 
+	if (context->obj_ctx) {
+		ab =audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
+		audit_log_format(ab, "opid=%d obj=%s",
+				 context->target_pid, context->obj_ctx);
+		audit_log_end(ab);
+	}
+
 	if (context->pwd && context->pwdmnt) {
 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
 		if (ab) {
@@ -1187,6 +1198,8 @@ void audit_syscall_exit(int valid, long return_code)
 	} else {
 		audit_free_names(context);
 		audit_free_aux(context);
+		kfree(context->obj_ctx);
+		context->obj_ctx = NULL;
 		kfree(context->filterkey);
 		context->filterkey = NULL;
 		tsk->audit_context = context;
@@ -1874,6 +1887,13 @@ int audit_sockaddr(int len, void *a)
 	return 0;
 }
 
+void __audit_ptrace(struct task_struct *t)
+{
+	struct audit_context *context = current->audit_context;
+	context->target_pid = t->pid;
+	security_getprocattr(t, "current", &context->obj_ctx);
+}
+
 /**
  * audit_avc_path - record the granting or denial of permissions
  * @dentry: dentry to record
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 4d50e06..ad7949a 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -18,6 +18,7 @@
 #include <linux/ptrace.h>
 #include <linux/security.h>
 #include <linux/signal.h>
+#include <linux/audit.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -161,6 +162,8 @@ int ptrace_attach(struct task_struct *task)
 {
 	int retval;
 
+	audit_ptrace(task);
+
 	retval = -EPERM;
 	if (task->pid <= 1)
 		goto out;

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-05 14:50 audit-ptrace patch (untested) Alexander Viro
@ 2007-03-06 14:46 ` Stephen Smalley
  2007-03-07  3:13   ` Alexander Viro
  0 siblings, 1 reply; 13+ messages in thread
From: Stephen Smalley @ 2007-03-06 14:46 UTC (permalink / raw)
  To: Alexander Viro; +Cc: Eric Paris, linux-audit, James Morris

On Mon, 2007-03-05 at 09:50 -0500, Alexander Viro wrote:
> That one is on top of security_getprocattr() patch.  See bz#228384...
> 
<snip>
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 89875b2..c8465ea 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
<snip>
> @@ -1874,6 +1887,13 @@ int audit_sockaddr(int len, void *a)
>  	return 0;
>  }
>  
> +void __audit_ptrace(struct task_struct *t)
> +{
> +	struct audit_context *context = current->audit_context;
> +	context->target_pid = t->pid;
> +	security_getprocattr(t, "current", &context->obj_ctx);
> +}

This will trigger a permission check in selinux_getprocattr, because
current != t.  So the audit system could be prevented from fetching the
context in this way based on the current task's permissions.   As with
the prior patch, I'd suggest using security_task_getsecid() and
security_secid_to_secctx() [or their selinux-specific equivalents,
selinux_get_task_sid and selinux_sid_to_string, already in use by audit]
instead for such internal access to security contexts.

-- 
Stephen Smalley
National Security Agency

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-06 14:46 ` Stephen Smalley
@ 2007-03-07  3:13   ` Alexander Viro
  2007-03-07 12:52     ` Stephen Smalley
  0 siblings, 1 reply; 13+ messages in thread
From: Alexander Viro @ 2007-03-07  3:13 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Eric Paris, linux-audit, James Morris

On Tue, Mar 06, 2007 at 09:46:14AM -0500, Stephen Smalley wrote:
> On Mon, 2007-03-05 at 09:50 -0500, Alexander Viro wrote:
> > That one is on top of security_getprocattr() patch.  See bz#228384...
> > 
> <snip>
> > diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> > index 89875b2..c8465ea 100644
> > --- a/kernel/auditsc.c
> > +++ b/kernel/auditsc.c
> <snip>
> > @@ -1874,6 +1887,13 @@ int audit_sockaddr(int len, void *a)
> >  	return 0;
> >  }
> >  
> > +void __audit_ptrace(struct task_struct *t)
> > +{
> > +	struct audit_context *context = current->audit_context;
> > +	context->target_pid = t->pid;
> > +	security_getprocattr(t, "current", &context->obj_ctx);
> > +}
> 
> This will trigger a permission check in selinux_getprocattr, because
> current != t.  So the audit system could be prevented from fetching the
> context in this way based on the current task's permissions.   As with
> the prior patch, I'd suggest using security_task_getsecid() and
> security_secid_to_secctx() [or their selinux-specific equivalents,
> selinux_get_task_sid and selinux_sid_to_string, already in use by audit]
> instead for such internal access to security contexts.

OK...  Here's combined patch (with switch to security_task_getsecid(), etc.)

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 4f5745a..6bbfe91 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1558,29 +1558,20 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
 				  size_t count, loff_t *ppos)
 {
 	struct inode * inode = file->f_path.dentry->d_inode;
-	unsigned long page;
+	char *p = NULL;
 	ssize_t length;
 	struct task_struct *task = get_proc_task(inode);
 
-	length = -ESRCH;
 	if (!task)
-		goto out_no_task;
-
-	if (count > PAGE_SIZE)
-		count = PAGE_SIZE;
-	length = -ENOMEM;
-	if (!(page = __get_free_page(GFP_KERNEL)))
-		goto out;
+		return -ESRCH;
 
 	length = security_getprocattr(task,
 				      (char*)file->f_path.dentry->d_name.name,
-				      (void*)page, count);
-	if (length >= 0)
-		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
-	free_page(page);
-out:
+				      &p);
 	put_task_struct(task);
-out_no_task:
+	if (length > 0)
+		length = simple_read_from_buffer(buf, count, ppos, p, length);
+	kfree(p);
 	return length;
 }
 
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 229fa01..31b0f40 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -90,6 +90,7 @@
 #define AUDIT_MQ_GETSETATTR	1315	/* POSIX MQ get/set attribute record type */
 #define AUDIT_KERNEL_OTHER	1316	/* For use by 3rd party modules */
 #define AUDIT_FD_PAIR		1317    /* audit record for pipe/socketpair */
+#define AUDIT_OBJ_PID		1318	/* ptrace target */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -351,6 +352,8 @@ extern void __audit_inode(const char *name, const struct inode *inode);
 extern void __audit_inode_child(const char *dname, const struct inode *inode,
 				const struct inode *parent);
 extern void __audit_inode_update(const struct inode *inode);
+extern void __audit_ptrace(struct task_struct *t);
+
 static inline int audit_dummy_context(void)
 {
 	void *p = current->audit_context;
@@ -376,6 +379,12 @@ static inline void audit_inode_update(const struct inode *inode) {
 		__audit_inode_update(inode);
 }
 
+static inline void audit_ptrace(struct task_struct *t)
+{
+	if (unlikely(!audit_dummy_context()))
+		__audit_ptrace(t);
+}
+
 				/* Private API (for audit.c only) */
 extern unsigned int audit_serial(void);
 extern void auditsc_get_stamp(struct audit_context *ctx,
@@ -476,6 +485,7 @@ extern int audit_n_rules;
 #define audit_mq_timedreceive(d,l,p,t) ({ 0; })
 #define audit_mq_notify(d,n) ({ 0; })
 #define audit_mq_getsetattr(d,s) ({ 0; })
+#define audit_ptrace(t) ((void)0)
 #define audit_n_rules 0
 #endif
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 7f88d97..47e82c1 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1324,7 +1324,7 @@ struct security_operations {
 
 	void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
 
- 	int (*getprocattr)(struct task_struct *p, char *name, void *value, size_t size);
+ 	int (*getprocattr)(struct task_struct *p, char *name, char **value);
  	int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size);
 	int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
 	void (*release_secctx)(char *secdata, u32 seclen);
@@ -2092,9 +2092,9 @@ static inline void security_d_instantiate (struct dentry *dentry, struct inode *
 	security_ops->d_instantiate (dentry, inode);
 }
 
-static inline int security_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
+static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
 {
-	return security_ops->getprocattr(p, name, value, size);
+	return security_ops->getprocattr(p, name, value);
 }
 
 static inline int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
@@ -2749,7 +2749,7 @@ static inline int security_sem_semop (struct sem_array * sma,
 static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
 { }
 
-static inline int security_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
+static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
 {
 	return -EINVAL;
 }
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 3599558..f8875cb 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -209,6 +209,9 @@ struct audit_context {
 	unsigned long	    personality;
 	int		    arch;
 
+	pid_t		    target_pid;
+	char *		    obj_ctx;
+
 #if AUDIT_DEBUG
 	int		    put_count;
 	int		    ino_count;
@@ -729,6 +732,7 @@ static inline void audit_free_context(struct audit_context *context)
 		audit_free_names(context);
 		audit_free_aux(context);
 		kfree(context->filterkey);
+		kfree(context->obj_ctx);
 		kfree(context);
 		context  = previous;
 	} while (context);
@@ -739,28 +743,26 @@ static inline void audit_free_context(struct audit_context *context)
 void audit_log_task_context(struct audit_buffer *ab)
 {
 	char *ctx = NULL;
-	ssize_t len = 0;
+	unsigned len;
+	int error;
+	u32 sid;
 
-	len = security_getprocattr(current, "current", NULL, 0);
-	if (len < 0) {
-		if (len != -EINVAL)
+	security_task_getsecid(current, &sid);
+	if (!sid)
+		return;
+
+	error = security_secid_to_secctx(sid, &ctx, &len);
+	if (error) {
+		if (error != -EINVAL)
 			goto error_path;
 		return;
 	}
 
-	ctx = kmalloc(len, GFP_KERNEL);
-	if (!ctx)
-		goto error_path;
-
-	len = security_getprocattr(current, "current", ctx, len);
-	if (len < 0 )
-		goto error_path;
-
 	audit_log_format(ab, " subj=%s", ctx);
+	kfree(ctx);
 	return;
 
 error_path:
-	kfree(ctx);
 	audit_panic("error in audit_log_task_context");
 	return;
 }
@@ -975,6 +977,16 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 		audit_log_end(ab);
 	}
 
+	if (context->target_pid) {
+		char *s = context->obj_ctx ? context->obj_ctx : "(none)";
+		ab =audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
+		if (ab) {
+			audit_log_format(ab, "opid=%d obj=%s",
+					 context->target_pid, s);
+			audit_log_end(ab);
+		}
+	}
+
 	if (context->pwd && context->pwdmnt) {
 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
 		if (ab) {
@@ -1195,6 +1207,9 @@ void audit_syscall_exit(int valid, long return_code)
 	} else {
 		audit_free_names(context);
 		audit_free_aux(context);
+		kfree(context->obj_ctx);
+		context->obj_ctx = NULL;
+		context->target_pid = 0;
 		kfree(context->filterkey);
 		context->filterkey = NULL;
 		tsk->audit_context = context;
@@ -1882,6 +1897,19 @@ int audit_sockaddr(int len, void *a)
 	return 0;
 }
 
+void __audit_ptrace(struct task_struct *t)
+{
+	struct audit_context *context = current->audit_context;
+	unsigned len;
+	u32 sid;
+
+	context->target_pid = t->pid;
+
+	security_task_getsecid(t, &sid);
+	if (sid)
+		security_secid_to_secctx(sid, &context->obj_ctx, &len);
+}
+
 /**
  * audit_avc_path - record the granting or denial of permissions
  * @dentry: dentry to record
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 4d50e06..ad7949a 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -18,6 +18,7 @@
 #include <linux/ptrace.h>
 #include <linux/security.h>
 #include <linux/signal.h>
+#include <linux/audit.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -161,6 +162,8 @@ int ptrace_attach(struct task_struct *task)
 {
 	int retval;
 
+	audit_ptrace(task);
+
 	retval = -EPERM;
 	if (task->pid <= 1)
 		goto out;
diff --git a/security/dummy.c b/security/dummy.c
index 558795b..8ffd764 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -907,7 +907,7 @@ static void dummy_d_instantiate (struct dentry *dentry, struct inode *inode)
 	return;
 }
 
-static int dummy_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
+static int dummy_getprocattr(struct task_struct *p, char *name, char **value)
 {
 	return -EINVAL;
 }
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b1ac22d..0b265a5 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4468,11 +4468,12 @@ static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
 }
 
 static int selinux_getprocattr(struct task_struct *p,
-			       char *name, void *value, size_t size)
+			       char *name, char **value)
 {
 	struct task_security_struct *tsec;
 	u32 sid;
 	int error;
+	unsigned len;
 
 	if (current != p) {
 		error = task_has_perm(current, p, PROCESS__GETATTR);
@@ -4500,7 +4501,10 @@ static int selinux_getprocattr(struct task_struct *p,
 	if (!sid)
 		return 0;
 
-	return selinux_getsecurity(sid, value, size);
+	error = security_sid_to_context(sid, value, &len);
+	if (error)
+		return error;
+	return len;
 }
 
 static int selinux_setprocattr(struct task_struct *p,

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-07  3:13   ` Alexander Viro
@ 2007-03-07 12:52     ` Stephen Smalley
  2007-03-07 16:22       ` James Morris
  2007-03-12 12:20       ` Alexander Viro
  0 siblings, 2 replies; 13+ messages in thread
From: Stephen Smalley @ 2007-03-07 12:52 UTC (permalink / raw)
  To: Alexander Viro; +Cc: Eric Paris, linux-audit, James Morris

On Tue, 2007-03-06 at 22:13 -0500, Alexander Viro wrote:
> OK...  Here's combined patch (with switch to security_task_getsecid(), etc.)

> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 3599558..f8875cb 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -729,6 +732,7 @@ static inline void audit_free_context(struct audit_context *context)
>  		audit_free_names(context);
>  		audit_free_aux(context);
>  		kfree(context->filterkey);
> +		kfree(context->obj_ctx);

Technically, this should be:
	 security_release_secctx(context->obj_ctx, context->ctxlen);
Although that does require keeping the length around, and the rest of
the audit code is already assuming it is just a string (unlike the
original user of these LSM hooks, the labeled IPSEC code).

> @@ -739,28 +743,26 @@ static inline void audit_free_context(struct audit_context *context)
>  void audit_log_task_context(struct audit_buffer *ab)
>  {
>  	char *ctx = NULL;
> -	ssize_t len = 0;
> +	unsigned len;
> +	int error;
> +	u32 sid;
>  
> -	len = security_getprocattr(current, "current", NULL, 0);
> -	if (len < 0) {
> -		if (len != -EINVAL)
> +	security_task_getsecid(current, &sid);
> +	if (!sid)
> +		return;
> +
> +	error = security_secid_to_secctx(sid, &ctx, &len);
> +	if (error) {
> +		if (error != -EINVAL)
>  			goto error_path;
>  		return;
>  	}
>  
> -	ctx = kmalloc(len, GFP_KERNEL);
> -	if (!ctx)
> -		goto error_path;
> -
> -	len = security_getprocattr(current, "current", ctx, len);
> -	if (len < 0 )
> -		goto error_path;
> -
>  	audit_log_format(ab, " subj=%s", ctx);
> +	kfree(ctx);

As above, technically should be:
	 security_release_secctx(ctx,len).

> @@ -1195,6 +1207,9 @@ void audit_syscall_exit(int valid, long return_code)
>  	} else {
>  		audit_free_names(context);
>  		audit_free_aux(context);
> +		kfree(context->obj_ctx);

And again.

Otherwise, looks fine.

-- 
Stephen Smalley
National Security Agency

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-07 12:52     ` Stephen Smalley
@ 2007-03-07 16:22       ` James Morris
  2007-03-12 12:20       ` Alexander Viro
  1 sibling, 0 replies; 13+ messages in thread
From: James Morris @ 2007-03-07 16:22 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Eric Paris, linux-audit

On Wed, 7 Mar 2007, Stephen Smalley wrote:

> >  		audit_free_aux(context);
> >  		kfree(context->filterkey);
> > +		kfree(context->obj_ctx);
> 
> Technically, this should be:
> 	 security_release_secctx(context->obj_ctx, context->ctxlen);
> Although that does require keeping the length around, and the rest of
> the audit code is already assuming it is just a string (unlike the
> original user of these LSM hooks, the labeled IPSEC code).

I think these needs to be fixed before merge, as the presence of existing 
mistakes doesn't justify adding new ones.


- James
-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-07 12:52     ` Stephen Smalley
  2007-03-07 16:22       ` James Morris
@ 2007-03-12 12:20       ` Alexander Viro
  2007-03-12 13:07         ` Stephen Smalley
                           ` (2 more replies)
  1 sibling, 3 replies; 13+ messages in thread
From: Alexander Viro @ 2007-03-12 12:20 UTC (permalink / raw)
  To: Stephen Smalley; +Cc: Eric Paris, linux-audit, James Morris

	OK, you've convinced me - I'm switching to selinux-specific ones
in kernel/auditsc.c.  Updated patch follows, should fix 228409 and
228384.

diff --git a/fs/proc/base.c b/fs/proc/base.c
index 4f5745a..6bbfe91 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1558,29 +1558,20 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
 				  size_t count, loff_t *ppos)
 {
 	struct inode * inode = file->f_path.dentry->d_inode;
-	unsigned long page;
+	char *p = NULL;
 	ssize_t length;
 	struct task_struct *task = get_proc_task(inode);
 
-	length = -ESRCH;
 	if (!task)
-		goto out_no_task;
-
-	if (count > PAGE_SIZE)
-		count = PAGE_SIZE;
-	length = -ENOMEM;
-	if (!(page = __get_free_page(GFP_KERNEL)))
-		goto out;
+		return -ESRCH;
 
 	length = security_getprocattr(task,
 				      (char*)file->f_path.dentry->d_name.name,
-				      (void*)page, count);
-	if (length >= 0)
-		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
-	free_page(page);
-out:
+				      &p);
 	put_task_struct(task);
-out_no_task:
+	if (length > 0)
+		length = simple_read_from_buffer(buf, count, ppos, p, length);
+	kfree(p);
 	return length;
 }
 
diff --git a/include/linux/audit.h b/include/linux/audit.h
index 229fa01..31b0f40 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -90,6 +90,7 @@
 #define AUDIT_MQ_GETSETATTR	1315	/* POSIX MQ get/set attribute record type */
 #define AUDIT_KERNEL_OTHER	1316	/* For use by 3rd party modules */
 #define AUDIT_FD_PAIR		1317    /* audit record for pipe/socketpair */
+#define AUDIT_OBJ_PID		1318	/* ptrace target */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
@@ -351,6 +352,8 @@ extern void __audit_inode(const char *name, const struct inode *inode);
 extern void __audit_inode_child(const char *dname, const struct inode *inode,
 				const struct inode *parent);
 extern void __audit_inode_update(const struct inode *inode);
+extern void __audit_ptrace(struct task_struct *t);
+
 static inline int audit_dummy_context(void)
 {
 	void *p = current->audit_context;
@@ -376,6 +379,12 @@ static inline void audit_inode_update(const struct inode *inode) {
 		__audit_inode_update(inode);
 }
 
+static inline void audit_ptrace(struct task_struct *t)
+{
+	if (unlikely(!audit_dummy_context()))
+		__audit_ptrace(t);
+}
+
 				/* Private API (for audit.c only) */
 extern unsigned int audit_serial(void);
 extern void auditsc_get_stamp(struct audit_context *ctx,
@@ -476,6 +485,7 @@ extern int audit_n_rules;
 #define audit_mq_timedreceive(d,l,p,t) ({ 0; })
 #define audit_mq_notify(d,n) ({ 0; })
 #define audit_mq_getsetattr(d,s) ({ 0; })
+#define audit_ptrace(t) ((void)0)
 #define audit_n_rules 0
 #endif
 
diff --git a/include/linux/security.h b/include/linux/security.h
index 7f88d97..47e82c1 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -1324,7 +1324,7 @@ struct security_operations {
 
 	void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
 
- 	int (*getprocattr)(struct task_struct *p, char *name, void *value, size_t size);
+ 	int (*getprocattr)(struct task_struct *p, char *name, char **value);
  	int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size);
 	int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
 	void (*release_secctx)(char *secdata, u32 seclen);
@@ -2092,9 +2092,9 @@ static inline void security_d_instantiate (struct dentry *dentry, struct inode *
 	security_ops->d_instantiate (dentry, inode);
 }
 
-static inline int security_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
+static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
 {
-	return security_ops->getprocattr(p, name, value, size);
+	return security_ops->getprocattr(p, name, value);
 }
 
 static inline int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
@@ -2749,7 +2749,7 @@ static inline int security_sem_semop (struct sem_array * sma,
 static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
 { }
 
-static inline int security_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
+static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
 {
 	return -EINVAL;
 }
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index 3599558..f489fed 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -209,6 +209,9 @@ struct audit_context {
 	unsigned long	    personality;
 	int		    arch;
 
+	pid_t		    target_pid;
+	char *		    obj_ctx;
+
 #if AUDIT_DEBUG
 	int		    put_count;
 	int		    ino_count;
@@ -729,6 +732,7 @@ static inline void audit_free_context(struct audit_context *context)
 		audit_free_names(context);
 		audit_free_aux(context);
 		kfree(context->filterkey);
+		kfree(context->obj_ctx);
 		kfree(context);
 		context  = previous;
 	} while (context);
@@ -739,28 +743,26 @@ static inline void audit_free_context(struct audit_context *context)
 void audit_log_task_context(struct audit_buffer *ab)
 {
 	char *ctx = NULL;
-	ssize_t len = 0;
+	unsigned len;
+	int error;
+	u32 sid;
 
-	len = security_getprocattr(current, "current", NULL, 0);
-	if (len < 0) {
-		if (len != -EINVAL)
+	selinux_get_task_sid(current, &sid);
+	if (!sid)
+		return;
+
+	error = selinux_sid_to_string(sid, &ctx, &len);
+	if (error) {
+		if (error != -EINVAL)
 			goto error_path;
 		return;
 	}
 
-	ctx = kmalloc(len, GFP_KERNEL);
-	if (!ctx)
-		goto error_path;
-
-	len = security_getprocattr(current, "current", ctx, len);
-	if (len < 0 )
-		goto error_path;
-
 	audit_log_format(ab, " subj=%s", ctx);
+	kfree(ctx);
 	return;
 
 error_path:
-	kfree(ctx);
 	audit_panic("error in audit_log_task_context");
 	return;
 }
@@ -975,6 +977,16 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 		audit_log_end(ab);
 	}
 
+	if (context->target_pid) {
+		char *s = context->obj_ctx ? context->obj_ctx : "(none)";
+		ab =audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
+		if (ab) {
+			audit_log_format(ab, "opid=%d obj=%s",
+					 context->target_pid, s);
+			audit_log_end(ab);
+		}
+	}
+
 	if (context->pwd && context->pwdmnt) {
 		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
 		if (ab) {
@@ -1195,6 +1207,9 @@ void audit_syscall_exit(int valid, long return_code)
 	} else {
 		audit_free_names(context);
 		audit_free_aux(context);
+		kfree(context->obj_ctx);
+		context->obj_ctx = NULL;
+		context->target_pid = 0;
 		kfree(context->filterkey);
 		context->filterkey = NULL;
 		tsk->audit_context = context;
@@ -1882,6 +1897,19 @@ int audit_sockaddr(int len, void *a)
 	return 0;
 }
 
+void __audit_ptrace(struct task_struct *t)
+{
+	struct audit_context *context = current->audit_context;
+	unsigned len;
+	u32 sid;
+
+	context->target_pid = t->pid;
+
+	selinux_get_task_sid(t, &sid);
+	if (sid)
+		selinux_sid_to_string(sid, &context->obj_ctx, &len);
+}
+
 /**
  * audit_avc_path - record the granting or denial of permissions
  * @dentry: dentry to record
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 4d50e06..ad7949a 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -18,6 +18,7 @@
 #include <linux/ptrace.h>
 #include <linux/security.h>
 #include <linux/signal.h>
+#include <linux/audit.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -161,6 +162,8 @@ int ptrace_attach(struct task_struct *task)
 {
 	int retval;
 
+	audit_ptrace(task);
+
 	retval = -EPERM;
 	if (task->pid <= 1)
 		goto out;
diff --git a/security/dummy.c b/security/dummy.c
index 558795b..8ffd764 100644
--- a/security/dummy.c
+++ b/security/dummy.c
@@ -907,7 +907,7 @@ static void dummy_d_instantiate (struct dentry *dentry, struct inode *inode)
 	return;
 }
 
-static int dummy_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
+static int dummy_getprocattr(struct task_struct *p, char *name, char **value)
 {
 	return -EINVAL;
 }
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index b1ac22d..0b265a5 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4468,11 +4468,12 @@ static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
 }
 
 static int selinux_getprocattr(struct task_struct *p,
-			       char *name, void *value, size_t size)
+			       char *name, char **value)
 {
 	struct task_security_struct *tsec;
 	u32 sid;
 	int error;
+	unsigned len;
 
 	if (current != p) {
 		error = task_has_perm(current, p, PROCESS__GETATTR);
@@ -4500,7 +4501,10 @@ static int selinux_getprocattr(struct task_struct *p,
 	if (!sid)
 		return 0;
 
-	return selinux_getsecurity(sid, value, size);
+	error = security_sid_to_context(sid, value, &len);
+	if (error)
+		return error;
+	return len;
 }
 
 static int selinux_setprocattr(struct task_struct *p,

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-12 12:20       ` Alexander Viro
@ 2007-03-12 13:07         ` Stephen Smalley
  2007-03-12 14:16         ` James Morris
  2007-03-13 19:00         ` Amy Griffis
  2 siblings, 0 replies; 13+ messages in thread
From: Stephen Smalley @ 2007-03-12 13:07 UTC (permalink / raw)
  To: Alexander Viro; +Cc: Eric Paris, linux-audit, James Morris

On Mon, 2007-03-12 at 08:20 -0400, Alexander Viro wrote:
> 	OK, you've convinced me - I'm switching to selinux-specific ones
> in kernel/auditsc.c.  Updated patch follows, should fix 228409 and
> 228384.

Acked-by: Stephen Smalley <sds@tycho.nsa.gov>

> 
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index 4f5745a..6bbfe91 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -1558,29 +1558,20 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
>  				  size_t count, loff_t *ppos)
>  {
>  	struct inode * inode = file->f_path.dentry->d_inode;
> -	unsigned long page;
> +	char *p = NULL;
>  	ssize_t length;
>  	struct task_struct *task = get_proc_task(inode);
>  
> -	length = -ESRCH;
>  	if (!task)
> -		goto out_no_task;
> -
> -	if (count > PAGE_SIZE)
> -		count = PAGE_SIZE;
> -	length = -ENOMEM;
> -	if (!(page = __get_free_page(GFP_KERNEL)))
> -		goto out;
> +		return -ESRCH;
>  
>  	length = security_getprocattr(task,
>  				      (char*)file->f_path.dentry->d_name.name,
> -				      (void*)page, count);
> -	if (length >= 0)
> -		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
> -	free_page(page);
> -out:
> +				      &p);
>  	put_task_struct(task);
> -out_no_task:
> +	if (length > 0)
> +		length = simple_read_from_buffer(buf, count, ppos, p, length);
> +	kfree(p);
>  	return length;
>  }
>  
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 229fa01..31b0f40 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -90,6 +90,7 @@
>  #define AUDIT_MQ_GETSETATTR	1315	/* POSIX MQ get/set attribute record type */
>  #define AUDIT_KERNEL_OTHER	1316	/* For use by 3rd party modules */
>  #define AUDIT_FD_PAIR		1317    /* audit record for pipe/socketpair */
> +#define AUDIT_OBJ_PID		1318	/* ptrace target */
>  
>  #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
>  #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
> @@ -351,6 +352,8 @@ extern void __audit_inode(const char *name, const struct inode *inode);
>  extern void __audit_inode_child(const char *dname, const struct inode *inode,
>  				const struct inode *parent);
>  extern void __audit_inode_update(const struct inode *inode);
> +extern void __audit_ptrace(struct task_struct *t);
> +
>  static inline int audit_dummy_context(void)
>  {
>  	void *p = current->audit_context;
> @@ -376,6 +379,12 @@ static inline void audit_inode_update(const struct inode *inode) {
>  		__audit_inode_update(inode);
>  }
>  
> +static inline void audit_ptrace(struct task_struct *t)
> +{
> +	if (unlikely(!audit_dummy_context()))
> +		__audit_ptrace(t);
> +}
> +
>  				/* Private API (for audit.c only) */
>  extern unsigned int audit_serial(void);
>  extern void auditsc_get_stamp(struct audit_context *ctx,
> @@ -476,6 +485,7 @@ extern int audit_n_rules;
>  #define audit_mq_timedreceive(d,l,p,t) ({ 0; })
>  #define audit_mq_notify(d,n) ({ 0; })
>  #define audit_mq_getsetattr(d,s) ({ 0; })
> +#define audit_ptrace(t) ((void)0)
>  #define audit_n_rules 0
>  #endif
>  
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 7f88d97..47e82c1 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -1324,7 +1324,7 @@ struct security_operations {
>  
>  	void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
>  
> - 	int (*getprocattr)(struct task_struct *p, char *name, void *value, size_t size);
> + 	int (*getprocattr)(struct task_struct *p, char *name, char **value);
>   	int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size);
>  	int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
>  	void (*release_secctx)(char *secdata, u32 seclen);
> @@ -2092,9 +2092,9 @@ static inline void security_d_instantiate (struct dentry *dentry, struct inode *
>  	security_ops->d_instantiate (dentry, inode);
>  }
>  
> -static inline int security_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
> +static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
>  {
> -	return security_ops->getprocattr(p, name, value, size);
> +	return security_ops->getprocattr(p, name, value);
>  }
>  
>  static inline int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
> @@ -2749,7 +2749,7 @@ static inline int security_sem_semop (struct sem_array * sma,
>  static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
>  { }
>  
> -static inline int security_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
> +static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
>  {
>  	return -EINVAL;
>  }
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 3599558..f489fed 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -209,6 +209,9 @@ struct audit_context {
>  	unsigned long	    personality;
>  	int		    arch;
>  
> +	pid_t		    target_pid;
> +	char *		    obj_ctx;
> +
>  #if AUDIT_DEBUG
>  	int		    put_count;
>  	int		    ino_count;
> @@ -729,6 +732,7 @@ static inline void audit_free_context(struct audit_context *context)
>  		audit_free_names(context);
>  		audit_free_aux(context);
>  		kfree(context->filterkey);
> +		kfree(context->obj_ctx);
>  		kfree(context);
>  		context  = previous;
>  	} while (context);
> @@ -739,28 +743,26 @@ static inline void audit_free_context(struct audit_context *context)
>  void audit_log_task_context(struct audit_buffer *ab)
>  {
>  	char *ctx = NULL;
> -	ssize_t len = 0;
> +	unsigned len;
> +	int error;
> +	u32 sid;
>  
> -	len = security_getprocattr(current, "current", NULL, 0);
> -	if (len < 0) {
> -		if (len != -EINVAL)
> +	selinux_get_task_sid(current, &sid);
> +	if (!sid)
> +		return;
> +
> +	error = selinux_sid_to_string(sid, &ctx, &len);
> +	if (error) {
> +		if (error != -EINVAL)
>  			goto error_path;
>  		return;
>  	}
>  
> -	ctx = kmalloc(len, GFP_KERNEL);
> -	if (!ctx)
> -		goto error_path;
> -
> -	len = security_getprocattr(current, "current", ctx, len);
> -	if (len < 0 )
> -		goto error_path;
> -
>  	audit_log_format(ab, " subj=%s", ctx);
> +	kfree(ctx);
>  	return;
>  
>  error_path:
> -	kfree(ctx);
>  	audit_panic("error in audit_log_task_context");
>  	return;
>  }
> @@ -975,6 +977,16 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
>  		audit_log_end(ab);
>  	}
>  
> +	if (context->target_pid) {
> +		char *s = context->obj_ctx ? context->obj_ctx : "(none)";
> +		ab =audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
> +		if (ab) {
> +			audit_log_format(ab, "opid=%d obj=%s",
> +					 context->target_pid, s);
> +			audit_log_end(ab);
> +		}
> +	}
> +
>  	if (context->pwd && context->pwdmnt) {
>  		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
>  		if (ab) {
> @@ -1195,6 +1207,9 @@ void audit_syscall_exit(int valid, long return_code)
>  	} else {
>  		audit_free_names(context);
>  		audit_free_aux(context);
> +		kfree(context->obj_ctx);
> +		context->obj_ctx = NULL;
> +		context->target_pid = 0;
>  		kfree(context->filterkey);
>  		context->filterkey = NULL;
>  		tsk->audit_context = context;
> @@ -1882,6 +1897,19 @@ int audit_sockaddr(int len, void *a)
>  	return 0;
>  }
>  
> +void __audit_ptrace(struct task_struct *t)
> +{
> +	struct audit_context *context = current->audit_context;
> +	unsigned len;
> +	u32 sid;
> +
> +	context->target_pid = t->pid;
> +
> +	selinux_get_task_sid(t, &sid);
> +	if (sid)
> +		selinux_sid_to_string(sid, &context->obj_ctx, &len);
> +}
> +
>  /**
>   * audit_avc_path - record the granting or denial of permissions
>   * @dentry: dentry to record
> diff --git a/kernel/ptrace.c b/kernel/ptrace.c
> index 4d50e06..ad7949a 100644
> --- a/kernel/ptrace.c
> +++ b/kernel/ptrace.c
> @@ -18,6 +18,7 @@
>  #include <linux/ptrace.h>
>  #include <linux/security.h>
>  #include <linux/signal.h>
> +#include <linux/audit.h>
>  
>  #include <asm/pgtable.h>
>  #include <asm/uaccess.h>
> @@ -161,6 +162,8 @@ int ptrace_attach(struct task_struct *task)
>  {
>  	int retval;
>  
> +	audit_ptrace(task);
> +
>  	retval = -EPERM;
>  	if (task->pid <= 1)
>  		goto out;
> diff --git a/security/dummy.c b/security/dummy.c
> index 558795b..8ffd764 100644
> --- a/security/dummy.c
> +++ b/security/dummy.c
> @@ -907,7 +907,7 @@ static void dummy_d_instantiate (struct dentry *dentry, struct inode *inode)
>  	return;
>  }
>  
> -static int dummy_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
> +static int dummy_getprocattr(struct task_struct *p, char *name, char **value)
>  {
>  	return -EINVAL;
>  }
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index b1ac22d..0b265a5 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -4468,11 +4468,12 @@ static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
>  }
>  
>  static int selinux_getprocattr(struct task_struct *p,
> -			       char *name, void *value, size_t size)
> +			       char *name, char **value)
>  {
>  	struct task_security_struct *tsec;
>  	u32 sid;
>  	int error;
> +	unsigned len;
>  
>  	if (current != p) {
>  		error = task_has_perm(current, p, PROCESS__GETATTR);
> @@ -4500,7 +4501,10 @@ static int selinux_getprocattr(struct task_struct *p,
>  	if (!sid)
>  		return 0;
>  
> -	return selinux_getsecurity(sid, value, size);
> +	error = security_sid_to_context(sid, value, &len);
> +	if (error)
> +		return error;
> +	return len;
>  }
>  
>  static int selinux_setprocattr(struct task_struct *p,
-- 
Stephen Smalley
National Security Agency

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-12 12:20       ` Alexander Viro
  2007-03-12 13:07         ` Stephen Smalley
@ 2007-03-12 14:16         ` James Morris
  2007-03-12 16:19           ` Alexander Viro
  2007-03-13 19:00         ` Amy Griffis
  2 siblings, 1 reply; 13+ messages in thread
From: James Morris @ 2007-03-12 14:16 UTC (permalink / raw)
  To: Alexander Viro; +Cc: Eric Paris, linux-audit

On Mon, 12 Mar 2007, Alexander Viro wrote:

> 	OK, you've convinced me - I'm switching to selinux-specific ones
> in kernel/auditsc.c.  Updated patch follows, should fix 228409 and
> 228384.

Al, I think this needs to go into Linus' tree and -stable to fix the 
crash.  Do you want to forward it to Linus ?  (I could, but it's a large 
patch for a bugfix and he'd probably be happier seeing it from you at 
this point in the development cycle).


Acked-by: James Morris <jmorris@namei.org>



> 
> diff --git a/fs/proc/base.c b/fs/proc/base.c
> index 4f5745a..6bbfe91 100644
> --- a/fs/proc/base.c
> +++ b/fs/proc/base.c
> @@ -1558,29 +1558,20 @@ static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
>  				  size_t count, loff_t *ppos)
>  {
>  	struct inode * inode = file->f_path.dentry->d_inode;
> -	unsigned long page;
> +	char *p = NULL;
>  	ssize_t length;
>  	struct task_struct *task = get_proc_task(inode);
>  
> -	length = -ESRCH;
>  	if (!task)
> -		goto out_no_task;
> -
> -	if (count > PAGE_SIZE)
> -		count = PAGE_SIZE;
> -	length = -ENOMEM;
> -	if (!(page = __get_free_page(GFP_KERNEL)))
> -		goto out;
> +		return -ESRCH;
>  
>  	length = security_getprocattr(task,
>  				      (char*)file->f_path.dentry->d_name.name,
> -				      (void*)page, count);
> -	if (length >= 0)
> -		length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
> -	free_page(page);
> -out:
> +				      &p);
>  	put_task_struct(task);
> -out_no_task:
> +	if (length > 0)
> +		length = simple_read_from_buffer(buf, count, ppos, p, length);
> +	kfree(p);
>  	return length;
>  }
>  
> diff --git a/include/linux/audit.h b/include/linux/audit.h
> index 229fa01..31b0f40 100644
> --- a/include/linux/audit.h
> +++ b/include/linux/audit.h
> @@ -90,6 +90,7 @@
>  #define AUDIT_MQ_GETSETATTR	1315	/* POSIX MQ get/set attribute record type */
>  #define AUDIT_KERNEL_OTHER	1316	/* For use by 3rd party modules */
>  #define AUDIT_FD_PAIR		1317    /* audit record for pipe/socketpair */
> +#define AUDIT_OBJ_PID		1318	/* ptrace target */
>  
>  #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
>  #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
> @@ -351,6 +352,8 @@ extern void __audit_inode(const char *name, const struct inode *inode);
>  extern void __audit_inode_child(const char *dname, const struct inode *inode,
>  				const struct inode *parent);
>  extern void __audit_inode_update(const struct inode *inode);
> +extern void __audit_ptrace(struct task_struct *t);
> +
>  static inline int audit_dummy_context(void)
>  {
>  	void *p = current->audit_context;
> @@ -376,6 +379,12 @@ static inline void audit_inode_update(const struct inode *inode) {
>  		__audit_inode_update(inode);
>  }
>  
> +static inline void audit_ptrace(struct task_struct *t)
> +{
> +	if (unlikely(!audit_dummy_context()))
> +		__audit_ptrace(t);
> +}
> +
>  				/* Private API (for audit.c only) */
>  extern unsigned int audit_serial(void);
>  extern void auditsc_get_stamp(struct audit_context *ctx,
> @@ -476,6 +485,7 @@ extern int audit_n_rules;
>  #define audit_mq_timedreceive(d,l,p,t) ({ 0; })
>  #define audit_mq_notify(d,n) ({ 0; })
>  #define audit_mq_getsetattr(d,s) ({ 0; })
> +#define audit_ptrace(t) ((void)0)
>  #define audit_n_rules 0
>  #endif
>  
> diff --git a/include/linux/security.h b/include/linux/security.h
> index 7f88d97..47e82c1 100644
> --- a/include/linux/security.h
> +++ b/include/linux/security.h
> @@ -1324,7 +1324,7 @@ struct security_operations {
>  
>  	void (*d_instantiate) (struct dentry *dentry, struct inode *inode);
>  
> - 	int (*getprocattr)(struct task_struct *p, char *name, void *value, size_t size);
> + 	int (*getprocattr)(struct task_struct *p, char *name, char **value);
>   	int (*setprocattr)(struct task_struct *p, char *name, void *value, size_t size);
>  	int (*secid_to_secctx)(u32 secid, char **secdata, u32 *seclen);
>  	void (*release_secctx)(char *secdata, u32 seclen);
> @@ -2092,9 +2092,9 @@ static inline void security_d_instantiate (struct dentry *dentry, struct inode *
>  	security_ops->d_instantiate (dentry, inode);
>  }
>  
> -static inline int security_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
> +static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
>  {
> -	return security_ops->getprocattr(p, name, value, size);
> +	return security_ops->getprocattr(p, name, value);
>  }
>  
>  static inline int security_setprocattr(struct task_struct *p, char *name, void *value, size_t size)
> @@ -2749,7 +2749,7 @@ static inline int security_sem_semop (struct sem_array * sma,
>  static inline void security_d_instantiate (struct dentry *dentry, struct inode *inode)
>  { }
>  
> -static inline int security_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
> +static inline int security_getprocattr(struct task_struct *p, char *name, char **value)
>  {
>  	return -EINVAL;
>  }
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 3599558..f489fed 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
> @@ -209,6 +209,9 @@ struct audit_context {
>  	unsigned long	    personality;
>  	int		    arch;
>  
> +	pid_t		    target_pid;
> +	char *		    obj_ctx;
> +
>  #if AUDIT_DEBUG
>  	int		    put_count;
>  	int		    ino_count;
> @@ -729,6 +732,7 @@ static inline void audit_free_context(struct audit_context *context)
>  		audit_free_names(context);
>  		audit_free_aux(context);
>  		kfree(context->filterkey);
> +		kfree(context->obj_ctx);
>  		kfree(context);
>  		context  = previous;
>  	} while (context);
> @@ -739,28 +743,26 @@ static inline void audit_free_context(struct audit_context *context)
>  void audit_log_task_context(struct audit_buffer *ab)
>  {
>  	char *ctx = NULL;
> -	ssize_t len = 0;
> +	unsigned len;
> +	int error;
> +	u32 sid;
>  
> -	len = security_getprocattr(current, "current", NULL, 0);
> -	if (len < 0) {
> -		if (len != -EINVAL)
> +	selinux_get_task_sid(current, &sid);
> +	if (!sid)
> +		return;
> +
> +	error = selinux_sid_to_string(sid, &ctx, &len);
> +	if (error) {
> +		if (error != -EINVAL)
>  			goto error_path;
>  		return;
>  	}
>  
> -	ctx = kmalloc(len, GFP_KERNEL);
> -	if (!ctx)
> -		goto error_path;
> -
> -	len = security_getprocattr(current, "current", ctx, len);
> -	if (len < 0 )
> -		goto error_path;
> -
>  	audit_log_format(ab, " subj=%s", ctx);
> +	kfree(ctx);
>  	return;
>  
>  error_path:
> -	kfree(ctx);
>  	audit_panic("error in audit_log_task_context");
>  	return;
>  }
> @@ -975,6 +977,16 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
>  		audit_log_end(ab);
>  	}
>  
> +	if (context->target_pid) {
> +		char *s = context->obj_ctx ? context->obj_ctx : "(none)";
> +		ab =audit_log_start(context, GFP_KERNEL, AUDIT_OBJ_PID);
> +		if (ab) {
> +			audit_log_format(ab, "opid=%d obj=%s",
> +					 context->target_pid, s);
> +			audit_log_end(ab);
> +		}
> +	}
> +
>  	if (context->pwd && context->pwdmnt) {
>  		ab = audit_log_start(context, GFP_KERNEL, AUDIT_CWD);
>  		if (ab) {
> @@ -1195,6 +1207,9 @@ void audit_syscall_exit(int valid, long return_code)
>  	} else {
>  		audit_free_names(context);
>  		audit_free_aux(context);
> +		kfree(context->obj_ctx);
> +		context->obj_ctx = NULL;
> +		context->target_pid = 0;
>  		kfree(context->filterkey);
>  		context->filterkey = NULL;
>  		tsk->audit_context = context;
> @@ -1882,6 +1897,19 @@ int audit_sockaddr(int len, void *a)
>  	return 0;
>  }
>  
> +void __audit_ptrace(struct task_struct *t)
> +{
> +	struct audit_context *context = current->audit_context;
> +	unsigned len;
> +	u32 sid;
> +
> +	context->target_pid = t->pid;
> +
> +	selinux_get_task_sid(t, &sid);
> +	if (sid)
> +		selinux_sid_to_string(sid, &context->obj_ctx, &len);
> +}
> +
>  /**
>   * audit_avc_path - record the granting or denial of permissions
>   * @dentry: dentry to record
> diff --git a/kernel/ptrace.c b/kernel/ptrace.c
> index 4d50e06..ad7949a 100644
> --- a/kernel/ptrace.c
> +++ b/kernel/ptrace.c
> @@ -18,6 +18,7 @@
>  #include <linux/ptrace.h>
>  #include <linux/security.h>
>  #include <linux/signal.h>
> +#include <linux/audit.h>
>  
>  #include <asm/pgtable.h>
>  #include <asm/uaccess.h>
> @@ -161,6 +162,8 @@ int ptrace_attach(struct task_struct *task)
>  {
>  	int retval;
>  
> +	audit_ptrace(task);
> +
>  	retval = -EPERM;
>  	if (task->pid <= 1)
>  		goto out;
> diff --git a/security/dummy.c b/security/dummy.c
> index 558795b..8ffd764 100644
> --- a/security/dummy.c
> +++ b/security/dummy.c
> @@ -907,7 +907,7 @@ static void dummy_d_instantiate (struct dentry *dentry, struct inode *inode)
>  	return;
>  }
>  
> -static int dummy_getprocattr(struct task_struct *p, char *name, void *value, size_t size)
> +static int dummy_getprocattr(struct task_struct *p, char *name, char **value)
>  {
>  	return -EINVAL;
>  }
> diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
> index b1ac22d..0b265a5 100644
> --- a/security/selinux/hooks.c
> +++ b/security/selinux/hooks.c
> @@ -4468,11 +4468,12 @@ static void selinux_d_instantiate (struct dentry *dentry, struct inode *inode)
>  }
>  
>  static int selinux_getprocattr(struct task_struct *p,
> -			       char *name, void *value, size_t size)
> +			       char *name, char **value)
>  {
>  	struct task_security_struct *tsec;
>  	u32 sid;
>  	int error;
> +	unsigned len;
>  
>  	if (current != p) {
>  		error = task_has_perm(current, p, PROCESS__GETATTR);
> @@ -4500,7 +4501,10 @@ static int selinux_getprocattr(struct task_struct *p,
>  	if (!sid)
>  		return 0;
>  
> -	return selinux_getsecurity(sid, value, size);
> +	error = security_sid_to_context(sid, value, &len);
> +	if (error)
> +		return error;
> +	return len;
>  }
>  
>  static int selinux_setprocattr(struct task_struct *p,
> 

-- 
James Morris
<jmorris@namei.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-12 14:16         ` James Morris
@ 2007-03-12 16:19           ` Alexander Viro
  0 siblings, 0 replies; 13+ messages in thread
From: Alexander Viro @ 2007-03-12 16:19 UTC (permalink / raw)
  To: James Morris; +Cc: Eric Paris, linux-audit

On Mon, Mar 12, 2007 at 10:16:42AM -0400, James Morris wrote:
> On Mon, 12 Mar 2007, Alexander Viro wrote:
> 
> > 	OK, you've convinced me - I'm switching to selinux-specific ones
> > in kernel/auditsc.c.  Updated patch follows, should fix 228409 and
> > 228384.
> 
> Al, I think this needs to go into Linus' tree and -stable to fix the 
> crash.  Do you want to forward it to Linus ?  (I could, but it's a large 
> patch for a bugfix and he'd probably be happier seeing it from you at 
> this point in the development cycle).

deadlock fix + security_getprocattr() sanitizing sent as two patches,
auditing ptrace target held back for now

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-12 12:20       ` Alexander Viro
  2007-03-12 13:07         ` Stephen Smalley
  2007-03-12 14:16         ` James Morris
@ 2007-03-13 19:00         ` Amy Griffis
  2007-03-13 19:39           ` Alexander Viro
  2007-03-14  3:06           ` Steve Grubb
  2 siblings, 2 replies; 13+ messages in thread
From: Amy Griffis @ 2007-03-13 19:00 UTC (permalink / raw)
  To: Alexander Viro; +Cc: Eric Paris, linux-audit, James Morris

Alexander Viro wrote:  [Mon Mar 12 2007, 08:20:55AM EDT]
> diff --git a/kernel/auditsc.c b/kernel/auditsc.c
> index 3599558..f489fed 100644
> --- a/kernel/auditsc.c
> +++ b/kernel/auditsc.c
<snip>
> +void __audit_ptrace(struct task_struct *t)
> +{
> +	struct audit_context *context = current->audit_context;
> +	unsigned len;
> +	u32 sid;
> +
> +	context->target_pid = t->pid;
> +
> +	selinux_get_task_sid(t, &sid);
> +	if (sid)
> +		selinux_sid_to_string(sid, &context->obj_ctx, &len);
> +}

Why did you choose to do the sid to string conversion at collection
time, rather than waiting for audit_log_exit?  In other code like this
we've been delaying the memory alloc until logging, in case we never
need it.

Amy

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-13 19:00         ` Amy Griffis
@ 2007-03-13 19:39           ` Alexander Viro
  2007-03-14 15:57             ` Amy Griffis
  2007-03-14  3:06           ` Steve Grubb
  1 sibling, 1 reply; 13+ messages in thread
From: Alexander Viro @ 2007-03-13 19:39 UTC (permalink / raw)
  To: Alexander Viro, Stephen Smalley, Eric Paris, linux-audit,
	James Morris

On Tue, Mar 13, 2007 at 03:00:46PM -0400, Amy Griffis wrote:
> > +	if (sid)
> > +		selinux_sid_to_string(sid, &context->obj_ctx, &len);
> > +}
> 
> Why did you choose to do the sid to string conversion at collection
> time, rather than waiting for audit_log_exit?

Narrower window for sid_to_context to change...

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-13 19:00         ` Amy Griffis
  2007-03-13 19:39           ` Alexander Viro
@ 2007-03-14  3:06           ` Steve Grubb
  1 sibling, 0 replies; 13+ messages in thread
From: Steve Grubb @ 2007-03-14  3:06 UTC (permalink / raw)
  To: linux-audit; +Cc: James Morris, Eric Paris

On Tuesday 13 March 2007 15:00:46 Amy Griffis wrote:
> Why did you choose to do the sid to string conversion at collection
> time, rather than waiting for audit_log_exit?  In other code like this
> we've been delaying the memory alloc until logging, in case we never
> need it.

Yeah I agree. We were waiting until the end to do the conversion in case we 
ultimately didn't need the string.

-Steve

^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: audit-ptrace patch (untested)
  2007-03-13 19:39           ` Alexander Viro
@ 2007-03-14 15:57             ` Amy Griffis
  0 siblings, 0 replies; 13+ messages in thread
From: Amy Griffis @ 2007-03-14 15:57 UTC (permalink / raw)
  To: Alexander Viro; +Cc: Eric Paris, linux-audit, James Morris

Alexander Viro wrote:  [Tue Mar 13 2007, 03:39:09PM EDT]
> On Tue, Mar 13, 2007 at 03:00:46PM -0400, Amy Griffis wrote:
> > > +	if (sid)
> > > +		selinux_sid_to_string(sid, &context->obj_ctx, &len);
> > > +}
> > 
> > Why did you choose to do the sid to string conversion at collection
> > time, rather than waiting for audit_log_exit?
> 
> Narrower window for sid_to_context to change...

Okay, I hadn't thought of that. But is it really more of a problem for
processes than for ipc or inodes? It's true that processes can change
their context, but that would change the sid, and we've already
collected that data. The sid-to-context-string mapping will only
change on policy load. I see the argument for narrowing the window,
but I'd like to see audit pick one way and stick to it.

Amy

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2007-03-14 15:57 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2007-03-05 14:50 audit-ptrace patch (untested) Alexander Viro
2007-03-06 14:46 ` Stephen Smalley
2007-03-07  3:13   ` Alexander Viro
2007-03-07 12:52     ` Stephen Smalley
2007-03-07 16:22       ` James Morris
2007-03-12 12:20       ` Alexander Viro
2007-03-12 13:07         ` Stephen Smalley
2007-03-12 14:16         ` James Morris
2007-03-12 16:19           ` Alexander Viro
2007-03-13 19:00         ` Amy Griffis
2007-03-13 19:39           ` Alexander Viro
2007-03-14 15:57             ` Amy Griffis
2007-03-14  3:06           ` Steve Grubb

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox