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 <[EMAIL PROTECTED]>



> 
> 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
<[EMAIL PROTECTED]>

--
Linux-audit mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/linux-audit

Reply via email to