NFSv4: Callers to nfs4_get_renew_cred() need to hold nfs_client->cl_lock
[safe/jmp/linux-2.6] / kernel / auditsc.c
index c070053..2a3f0af 100644 (file)
@@ -68,9 +68,6 @@
 
 #include "audit.h"
 
-extern struct list_head audit_filter_list[];
-extern int audit_ever_enabled;
-
 /* AUDIT_NAMES is the number of slots we reserve in the audit_context
  * for saving names from getname(). */
 #define AUDIT_NAMES    20
@@ -246,7 +243,11 @@ static inline int open_arg(int flags, int mask)
 
 static int audit_match_perm(struct audit_context *ctx, int mask)
 {
-       unsigned n = ctx->major;
+       unsigned n;
+       if (unlikely(!ctx))
+               return 0;
+       n = ctx->major;
+
        switch (audit_classify_syscall(ctx->arch, n)) {
        case 0: /* native */
                if ((mask & AUDIT_PERM_WRITE) &&
@@ -283,6 +284,23 @@ static int audit_match_perm(struct audit_context *ctx, int mask)
        }
 }
 
+static int audit_match_filetype(struct audit_context *ctx, int which)
+{
+       unsigned index = which & ~S_IFMT;
+       mode_t mode = which & S_IFMT;
+
+       if (unlikely(!ctx))
+               return 0;
+
+       if (index >= ctx->name_count)
+               return 0;
+       if (ctx->names[index].ino == -1)
+               return 0;
+       if ((ctx->names[index].mode ^ mode) & S_IFMT)
+               return 0;
+       return 1;
+}
+
 /*
  * We keep a linked list of fixed-sized (31 pointer) arrays of audit_chunk *;
  * ->first_trees points to its beginning, ->trees - to the current end of data.
@@ -527,14 +545,14 @@ static int audit_filter_rules(struct task_struct *tsk,
                           match for now to avoid losing information that
                           may be wanted.   An error message will also be
                           logged upon error */
-                       if (f->se_rule) {
+                       if (f->lsm_rule) {
                                if (need_sid) {
                                        security_task_getsecid(tsk, &sid);
                                        need_sid = 0;
                                }
                                result = security_audit_rule_match(sid, f->type,
                                                                  f->op,
-                                                                 f->se_rule,
+                                                                 f->lsm_rule,
                                                                  ctx);
                        }
                        break;
@@ -545,18 +563,18 @@ static int audit_filter_rules(struct task_struct *tsk,
                case AUDIT_OBJ_LEV_HIGH:
                        /* The above note for AUDIT_SUBJ_USER...AUDIT_SUBJ_CLR
                           also applies here */
-                       if (f->se_rule) {
+                       if (f->lsm_rule) {
                                /* Find files that match */
                                if (name) {
                                        result = security_audit_rule_match(
                                                   name->osid, f->type, f->op,
-                                                  f->se_rule, ctx);
+                                                  f->lsm_rule, ctx);
                                } else if (ctx) {
                                        for (j = 0; j < ctx->name_count; j++) {
                                                if (security_audit_rule_match(
                                                      ctx->names[j].osid,
                                                      f->type, f->op,
-                                                     f->se_rule, ctx)) {
+                                                     f->lsm_rule, ctx)) {
                                                        ++result;
                                                        break;
                                                }
@@ -569,7 +587,7 @@ static int audit_filter_rules(struct task_struct *tsk,
                                             aux = aux->next) {
                                                if (aux->type == AUDIT_IPC) {
                                                        struct audit_aux_data_ipcctl *axi = (void *)aux;
-                                                       if (security_audit_rule_match(axi->osid, f->type, f->op, f->se_rule, ctx)) {
+                                                       if (security_audit_rule_match(axi->osid, f->type, f->op, f->lsm_rule, ctx)) {
                                                                ++result;
                                                                break;
                                                        }
@@ -592,12 +610,15 @@ static int audit_filter_rules(struct task_struct *tsk,
                case AUDIT_PERM:
                        result = audit_match_perm(ctx, f->val);
                        break;
+               case AUDIT_FILETYPE:
+                       result = audit_match_filetype(ctx, f->val);
+                       break;
                }
 
                if (!result)
                        return 0;
        }
-       if (rule->filterkey)
+       if (rule->filterkey && ctx)
                ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC);
        switch (rule->action) {
        case AUDIT_NEVER:    *state = AUDIT_DISABLED;       break;
@@ -1095,7 +1116,7 @@ static int audit_log_single_execve_arg(struct audit_context *context,
                        audit_log_format(*ab, "[%d]", i);
                audit_log_format(*ab, "=");
                if (has_cntl)
-                       audit_log_hex(*ab, buf, to_send);
+                       audit_log_n_hex(*ab, buf, to_send);
                else
                        audit_log_format(*ab, "\"%s\"", buf);
                audit_log_format(*ab, "\n");
@@ -1183,13 +1204,13 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                                 (context->return_valid==AUDITSC_SUCCESS)?"yes":"no",
                                 context->return_code);
 
-       mutex_lock(&tty_mutex);
-       read_lock(&tasklist_lock);
+       spin_lock_irq(&tsk->sighand->siglock);
        if (tsk->signal && tsk->signal->tty && tsk->signal->tty->name)
                tty = tsk->signal->tty->name;
        else
                tty = "(none)";
-       read_unlock(&tasklist_lock);
+       spin_unlock_irq(&tsk->sighand->siglock);
+
        audit_log_format(ab,
                  " a0=%lx a1=%lx a2=%lx a3=%lx items=%d"
                  " ppid=%d pid=%d auid=%u uid=%u gid=%u"
@@ -1209,7 +1230,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                  context->egid, context->sgid, context->fsgid, tty,
                  tsk->sessionid);
 
-       mutex_unlock(&tty_mutex);
 
        audit_log_task_info(ab, tsk);
        if (context->filterkey) {
@@ -1296,7 +1316,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                        break; }
 
                case AUDIT_SOCKETCALL: {
-                       int i;
                        struct audit_aux_data_socketcall *axs = (void *)aux;
                        audit_log_format(ab, "nargs=%d", axs->nargs);
                        for (i=0; i<axs->nargs; i++)
@@ -1307,7 +1326,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                        struct audit_aux_data_sockaddr *axs = (void *)aux;
 
                        audit_log_format(ab, "saddr=");
-                       audit_log_hex(ab, axs->a, axs->len);
+                       audit_log_n_hex(ab, axs->a, axs->len);
                        break; }
 
                case AUDIT_FD_PAIR: {
@@ -1321,7 +1340,6 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 
        for (aux = context->aux_pids; aux; aux = aux->next) {
                struct audit_aux_data_pids *axs = (void *)aux;
-               int i;
 
                for (i = 0; i < axs->pid_count; i++)
                        if (audit_log_pid_context(context, axs->target_pid[i],
@@ -1371,8 +1389,8 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                        default:
                                /* log the name's directory component */
                                audit_log_format(ab, " name=");
-                               audit_log_n_untrustedstring(ab, n->name_len,
-                                                           n->name);
+                               audit_log_n_untrustedstring(ab, n->name,
+                                                           n->name_len);
                        }
                } else
                        audit_log_format(ab, " name=(null)");
@@ -1441,7 +1459,6 @@ void audit_free(struct task_struct *tsk)
 
 /**
  * audit_syscall_entry - fill in an audit record at syscall entry
- * @tsk: task being audited
  * @arch: architecture type
  * @major: major syscall type (function)
  * @a1: additional syscall register 1
@@ -1465,7 +1482,8 @@ void audit_syscall_entry(int arch, int major,
        struct audit_context *context = tsk->audit_context;
        enum audit_state     state;
 
-       BUG_ON(!context);
+       if (unlikely(!context))
+               return;
 
        /*
         * This happens only on certain architectures that make system
@@ -1529,9 +1547,25 @@ void audit_syscall_entry(int arch, int major,
        context->ppid       = 0;
 }
 
+void audit_finish_fork(struct task_struct *child)
+{
+       struct audit_context *ctx = current->audit_context;
+       struct audit_context *p = child->audit_context;
+       if (!p || !ctx || !ctx->auditable)
+               return;
+       p->arch = ctx->arch;
+       p->major = ctx->major;
+       memcpy(p->argv, ctx->argv, sizeof(ctx->argv));
+       p->ctime = ctx->ctime;
+       p->dummy = ctx->dummy;
+       p->auditable = ctx->auditable;
+       p->in_syscall = ctx->in_syscall;
+       p->filterkey = kstrdup(ctx->filterkey, GFP_KERNEL);
+       p->ppid = current->pid;
+}
+
 /**
  * audit_syscall_exit - deallocate audit context after a system call
- * @tsk: task being audited
  * @valid: success/failure flag
  * @return_code: syscall return value
  *
@@ -1596,7 +1630,7 @@ static inline void handle_one(const struct inode *inode)
        if (likely(put_tree_ref(context, chunk)))
                return;
        if (unlikely(!grow_tree_refs(context))) {
-               printk(KERN_WARNING "out of memory, audit has lost a tree reference");
+               printk(KERN_WARNING "out of memory, audit has lost a tree reference\n");
                audit_set_auditable(context);
                audit_put_chunk(chunk);
                unroll_tree_refs(context, p, count);
@@ -1656,7 +1690,7 @@ retry:
                }
                /* too bad */
                printk(KERN_WARNING
-                       "out of memory, audit has lost a tree reference");
+                       "out of memory, audit has lost a tree reference\n");
                unroll_tree_refs(context, p, count);
                audit_set_auditable(context);
                return;
@@ -1752,13 +1786,13 @@ static int audit_inc_name_count(struct audit_context *context,
        if (context->name_count >= AUDIT_NAMES) {
                if (inode)
                        printk(KERN_DEBUG "name_count maxed, losing inode data: "
-                              "dev=%02x:%02x, inode=%lu",
+                              "dev=%02x:%02x, inode=%lu\n",
                               MAJOR(inode->i_sb->s_dev),
                               MINOR(inode->i_sb->s_dev),
                               inode->i_ino);
 
                else
-                       printk(KERN_DEBUG "name_count maxed, losing inode data");
+                       printk(KERN_DEBUG "name_count maxed, losing inode data\n");
                return 1;
        }
        context->name_count++;
@@ -1923,15 +1957,18 @@ EXPORT_SYMBOL_GPL(__audit_inode_child);
  *
  * Also sets the context as auditable.
  */
-void auditsc_get_stamp(struct audit_context *ctx,
+int auditsc_get_stamp(struct audit_context *ctx,
                       struct timespec *t, unsigned int *serial)
 {
+       if (!ctx->in_syscall)
+               return 0;
        if (!ctx->serial)
                ctx->serial = audit_serial();
        t->tv_sec  = ctx->ctime.tv_sec;
        t->tv_nsec = ctx->ctime.tv_nsec;
        *serial    = ctx->serial;
        ctx->auditable = 1;
+       return 1;
 }
 
 /* global counter which is incremented every time something logs in */
@@ -2361,12 +2398,9 @@ int __audit_signal_info(int sig, struct task_struct *t)
        struct audit_aux_data_pids *axp;
        struct task_struct *tsk = current;
        struct audit_context *ctx = tsk->audit_context;
-       extern pid_t audit_sig_pid;
-       extern uid_t audit_sig_uid;
-       extern u32 audit_sig_sid;
 
        if (audit_pid && t->tgid == audit_pid) {
-               if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1) {
+               if (sig == SIGTERM || sig == SIGHUP || sig == SIGUSR1 || sig == SIGUSR2) {
                        audit_sig_pid = tsk->pid;
                        if (tsk->loginuid != -1)
                                audit_sig_uid = tsk->loginuid;