]> err.no Git - linux-2.6/blobdiff - kernel/auditsc.c
[PATCH] Time: Introduce arch generic time accessors
[linux-2.6] / kernel / auditsc.c
index 174a3f6248928e5dc14462b1d37b6aeaee252176..9ebd96fda2958835a7d0d0aa6dc1993ee11f1098 100644 (file)
@@ -82,6 +82,9 @@ extern int audit_enabled;
  * path_lookup. */
 #define AUDIT_NAMES_RESERVED 7
 
+/* Indicates that audit should log the full pathname. */
+#define AUDIT_NAME_FULL -1
+
 /* When fs/namei.c:getname() is called, we store the pointer in name and
  * we don't let putname() free it (instead we free all of the saved
  * pointers at syscall exit time).
@@ -89,8 +92,9 @@ extern int audit_enabled;
  * Further, in fs/namei.c:path_lookup() we store the inode and device. */
 struct audit_names {
        const char      *name;
+       int             name_len;       /* number of name's characters to log */
+       unsigned        name_put;       /* call __putname() for this name */
        unsigned long   ino;
-       unsigned long   pino;
        dev_t           dev;
        umode_t         mode;
        uid_t           uid;
@@ -296,12 +300,10 @@ static int audit_filter_rules(struct task_struct *tsk,
                        break;
                case AUDIT_INODE:
                        if (name)
-                               result = (name->ino == f->val ||
-                                         name->pino == f->val);
+                               result = (name->ino == f->val);
                        else if (ctx) {
                                for (j = 0; j < ctx->name_count; j++) {
-                                       if (audit_comparator(ctx->names[j].ino, f->op, f->val) ||
-                                           audit_comparator(ctx->names[j].pino, f->op, f->val)) {
+                                       if (audit_comparator(ctx->names[j].ino, f->op, f->val)) {
                                                ++result;
                                                break;
                                        }
@@ -311,8 +313,7 @@ static int audit_filter_rules(struct task_struct *tsk,
                case AUDIT_WATCH:
                        if (name && rule->watch->ino != (unsigned long)-1)
                                result = (name->dev == rule->watch->dev &&
-                                         (name->ino == rule->watch->ino ||
-                                          name->pino == rule->watch->ino));
+                                         name->ino == rule->watch->ino);
                        break;
                case AUDIT_LOGINUID:
                        result = 0;
@@ -526,7 +527,7 @@ static inline void audit_free_names(struct audit_context *context)
 #endif
 
        for (i = 0; i < context->name_count; i++) {
-               if (context->names[i].name)
+               if (context->names[i].name && context->names[i].name_put)
                        __putname(context->names[i].name);
        }
        context->name_count = 0;
@@ -850,8 +851,7 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
                }
        }
        for (i = 0; i < context->name_count; i++) {
-               unsigned long ino  = context->names[i].ino;
-               unsigned long pino = context->names[i].pino;
+               struct audit_names *n = &context->names[i];
 
                ab = audit_log_start(context, GFP_KERNEL, AUDIT_PATH);
                if (!ab)
@@ -859,33 +859,47 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts
 
                audit_log_format(ab, "item=%d", i);
 
-               audit_log_format(ab, " name=");
-               if (context->names[i].name)
-                       audit_log_untrustedstring(ab, context->names[i].name);
-               else
-                       audit_log_format(ab, "(null)");
-
-               if (pino != (unsigned long)-1)
-                       audit_log_format(ab, " parent=%lu",  pino);
-               if (ino != (unsigned long)-1)
-                       audit_log_format(ab, " inode=%lu",  ino);
-               if ((pino != (unsigned long)-1) || (ino != (unsigned long)-1))
-                       audit_log_format(ab, " dev=%02x:%02x mode=%#o" 
-                                        " ouid=%u ogid=%u rdev=%02x:%02x", 
-                                        MAJOR(context->names[i].dev), 
-                                        MINOR(context->names[i].dev), 
-                                        context->names[i].mode, 
-                                        context->names[i].uid, 
-                                        context->names[i].gid, 
-                                        MAJOR(context->names[i].rdev), 
-                                        MINOR(context->names[i].rdev));
-               if (context->names[i].osid != 0) {
+               if (n->name) {
+                       switch(n->name_len) {
+                       case AUDIT_NAME_FULL:
+                               /* log the full path */
+                               audit_log_format(ab, " name=");
+                               audit_log_untrustedstring(ab, n->name);
+                               break;
+                       case 0:
+                               /* name was specified as a relative path and the
+                                * directory component is the cwd */
+                               audit_log_d_path(ab, " name=", context->pwd,
+                                                context->pwdmnt);
+                               break;
+                       default:
+                               /* log the name's directory component */
+                               audit_log_format(ab, " name=");
+                               audit_log_n_untrustedstring(ab, n->name_len,
+                                                           n->name);
+                       }
+               } else
+                       audit_log_format(ab, " name=(null)");
+
+               if (n->ino != (unsigned long)-1) {
+                       audit_log_format(ab, " inode=%lu"
+                                        " dev=%02x:%02x mode=%#o"
+                                        " ouid=%u ogid=%u rdev=%02x:%02x",
+                                        n->ino,
+                                        MAJOR(n->dev),
+                                        MINOR(n->dev),
+                                        n->mode,
+                                        n->uid,
+                                        n->gid,
+                                        MAJOR(n->rdev),
+                                        MINOR(n->rdev));
+               }
+               if (n->osid != 0) {
                        char *ctx = NULL;
                        u32 len;
                        if (selinux_ctxid_to_string(
-                               context->names[i].osid, &ctx, &len)) {
-                               audit_log_format(ab, " osid=%u",
-                                               context->names[i].osid);
+                               n->osid, &ctx, &len)) {
+                               audit_log_format(ab, " osid=%u", n->osid);
                                call_panic = 2;
                        } else
                                audit_log_format(ab, " obj=%s", ctx);
@@ -1075,6 +1089,8 @@ void __audit_getname(const char *name)
        }
        BUG_ON(context->name_count >= AUDIT_NAMES);
        context->names[context->name_count].name = name;
+       context->names[context->name_count].name_len = AUDIT_NAME_FULL;
+       context->names[context->name_count].name_put = 1;
        context->names[context->name_count].ino  = (unsigned long)-1;
        ++context->name_count;
        if (!context->pwd) {
@@ -1141,11 +1157,10 @@ static void audit_inode_context(int idx, const struct inode *inode)
  * audit_inode - store the inode and device from a lookup
  * @name: name being audited
  * @inode: inode being audited
- * @flags: lookup flags (as used in path_lookup())
  *
  * Called from fs/namei.c:path_lookup().
  */
-void __audit_inode(const char *name, const struct inode *inode, unsigned flags)
+void __audit_inode(const char *name, const struct inode *inode)
 {
        int idx;
        struct audit_context *context = current->audit_context;
@@ -1171,20 +1186,13 @@ void __audit_inode(const char *name, const struct inode *inode, unsigned flags)
                ++context->ino_count;
 #endif
        }
+       context->names[idx].ino   = inode->i_ino;
        context->names[idx].dev   = inode->i_sb->s_dev;
        context->names[idx].mode  = inode->i_mode;
        context->names[idx].uid   = inode->i_uid;
        context->names[idx].gid   = inode->i_gid;
        context->names[idx].rdev  = inode->i_rdev;
        audit_inode_context(idx, inode);
-       if ((flags & LOOKUP_PARENT) && (strcmp(name, "/") != 0) && 
-           (strcmp(name, ".") != 0)) {
-               context->names[idx].ino   = (unsigned long)-1;
-               context->names[idx].pino  = inode->i_ino;
-       } else {
-               context->names[idx].ino   = inode->i_ino;
-               context->names[idx].pino  = (unsigned long)-1;
-       }
 }
 
 /**
@@ -1206,34 +1214,40 @@ void __audit_inode_child(const char *dname, const struct inode *inode,
 {
        int idx;
        struct audit_context *context = current->audit_context;
+       const char *found_name = NULL;
+       int dirlen = 0;
 
        if (!context->in_syscall)
                return;
 
        /* determine matching parent */
        if (!dname)
-               goto no_match;
+               goto update_context;
        for (idx = 0; idx < context->name_count; idx++)
-               if (context->names[idx].pino == pino) {
+               if (context->names[idx].ino == pino) {
                        const char *name = context->names[idx].name;
 
                        if (!name)
                                continue;
 
-                       if (audit_compare_dname_path(dname, name) == 0)
-                               goto update_context;
+                       if (audit_compare_dname_path(dname, name, &dirlen) == 0) {
+                               context->names[idx].name_len = dirlen;
+                               found_name = name;
+                               break;
+                       }
                }
 
-no_match:
-       /* catch-all in case match not found */
+update_context:
        idx = context->name_count++;
-       context->names[idx].name  = NULL;
-       context->names[idx].pino  = pino;
 #if AUDIT_DEBUG
        context->ino_count++;
 #endif
+       /* Re-use the name belonging to the slot for a matching parent directory.
+        * All names for this context are relinquished in audit_free_names() */
+       context->names[idx].name = found_name;
+       context->names[idx].name_len = AUDIT_NAME_FULL;
+       context->names[idx].name_put = 0;       /* don't call __putname() */
 
-update_context:
        if (inode) {
                context->names[idx].ino   = inode->i_ino;
                context->names[idx].dev   = inode->i_sb->s_dev;
@@ -1242,7 +1256,8 @@ update_context:
                context->names[idx].gid   = inode->i_gid;
                context->names[idx].rdev  = inode->i_rdev;
                audit_inode_context(idx, inode);
-       }
+       } else
+               context->names[idx].ino   = (unsigned long)-1;
 }
 
 /**
@@ -1275,18 +1290,23 @@ void auditsc_get_stamp(struct audit_context *ctx,
  */
 int audit_set_loginuid(struct task_struct *task, uid_t loginuid)
 {
-       if (task->audit_context) {
-               struct audit_buffer *ab;
-
-               ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
-               if (ab) {
-                       audit_log_format(ab, "login pid=%d uid=%u "
-                               "old auid=%u new auid=%u",
-                               task->pid, task->uid, 
-                               task->audit_context->loginuid, loginuid);
-                       audit_log_end(ab);
+       struct audit_context *context = task->audit_context;
+
+       if (context) {
+               /* Only log if audit is enabled */
+               if (context->in_syscall) {
+                       struct audit_buffer *ab;
+
+                       ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_LOGIN);
+                       if (ab) {
+                               audit_log_format(ab, "login pid=%d uid=%u "
+                                       "old auid=%u new auid=%u",
+                                       task->pid, task->uid,
+                                       context->loginuid, loginuid);
+                               audit_log_end(ab);
+                       }
                }
-               task->audit_context->loginuid = loginuid;
+               context->loginuid = loginuid;
        }
        return 0;
 }
@@ -1538,6 +1558,7 @@ int __audit_ipc_obj(struct kern_ipc_perm *ipcp)
  * @uid: msgq user id
  * @gid: msgq group id
  * @mode: msgq mode (permissions)
+ * @ipcp: in-kernel IPC permissions
  *
  * Returns 0 for success or NULL context or < 0 on error.
  */