Whamcloud - gitweb
add null_audit command to lctl which will make audit silent. For testing purposes.
[fs/lustre-release.git] / lustre / smfs / audit.c
index 0e9d572..fd83c0c 100644 (file)
@@ -43,7 +43,7 @@
 
 static audit_op hook2audit(hook_op hook)
 {
-        audit_op opcode = AUDIT_NONE;
+        audit_op opcode = AUDIT_UNKNOWN;
 
         switch (hook) 
         {
@@ -71,16 +71,18 @@ static audit_op hook2audit(hook_op hook)
                         return AUDIT_SETATTR;
                         
                 case HOOK_SI_WRITE:
+                case HOOK_WRITE:
                         return AUDIT_WRITE;
                         
                 case HOOK_SI_READ:
+                case HOOK_READ:
                         return AUDIT_READ;
 
                 case HOOK_READDIR:
                         return AUDIT_READDIR;
 
                 default:
-                        return AUDIT_NONE;
+                        break;
         }
         
         return opcode;
@@ -123,14 +125,37 @@ struct inode * get_inode_from_hook(hook_op hook, void * msg)
 
         return inode;
 }
+
+static inline int smfs_get_inode_audit(struct inode *inode, __u64 *mask)
+{
+        struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_cache_fsfilt;
+        struct smfs_inode_info * smi = I2SMI(inode);
+        int rc = 0;
+        
+        /* omit __iopen__ dir */
+        if (inode->i_ino == SMFS_IOPEN_INO) {
+                *mask = AUDIT_OFF;
+                RETURN(-ENOENT);
+        }
+        if (smi->au_info.au_valid)
+                *mask = smi->au_info.au_mask;
+        else {
+                rc = fsfilt->fs_get_xattr(I2CI(inode), AUDIT_ATTR_EA,
+                                          mask, sizeof(*mask));
+                if (rc <= 0)
+                        *mask = AUDIT_OFF;
+                smi->au_info.au_valid = 1;
+                smi->au_info.au_mask = *mask;
+        }
+        RETURN(0);
+}
+
 /* is called also from fsfilt_smfs_get_info */
 int smfs_get_audit(struct super_block * sb, struct inode * parent,
                    struct inode * inode,  __u64 * mask)
 {
         struct smfs_super_info * smb = S2SMI(sb);
-        struct fsfilt_operations *fsfilt = smb->sm_fsfilt;
         struct obd_device * obd = smb->smsi_exp->exp_obd;
-        int rc;
         struct audit_priv * priv = NULL;
         
         ENTRY;
@@ -140,10 +165,6 @@ int smfs_get_audit(struct super_block * sb, struct inode * parent,
         
         priv = smfs_get_plg_priv(S2SMI(sb), SMFS_PLG_AUDIT);
               
-        /* omit __iopen__ dir */
-        if (parent->i_ino == SMFS_IOPEN_INO)
-                RETURN(-ENOENT);
-        
         if (!priv)
                 RETURN(-ENOENT);
         
@@ -155,26 +176,20 @@ int smfs_get_audit(struct super_block * sb, struct inode * parent,
                 (*mask) = priv->a_mask;
                 RETURN(0);
         }
-        /* get inode audit EA */
-        rc = fsfilt->fs_get_xattr(parent, AUDIT_ATTR_EA,
-                                  mask, sizeof(*mask));
-        if (rc <= 0)
-                RETURN(-ENODATA);
-        
-        /* check if parent has audit */
-        if (IS_AUDIT(*mask))
-                RETURN(0);
-        
-        if (!inode)
-                RETURN(-ENOENT);
         
-        rc = fsfilt->fs_get_xattr(inode, AUDIT_ATTR_EA,
-                                  mask, sizeof(*mask));
-        if (rc <= 0)
-                RETURN(-ENODATA);
+        /* get inode audit EA */
+        if (parent) {
+                smfs_get_inode_audit(parent, mask);
+                /* check if parent has audit */
+                if (IS_AUDIT(*mask))
+                        RETURN(0);
+        }
         
-        if (IS_AUDIT(*mask))
-                RETURN(0);
+        if (inode) {
+                smfs_get_inode_audit(inode, mask);
+                if (IS_AUDIT(*mask))
+                        RETURN(0);
+        }
 
         RETURN(-ENODATA);
 }
@@ -183,6 +198,7 @@ int smfs_audit_check(struct inode * parent, hook_op hook, int ret,
                      struct audit_priv * priv, void * msg)
 {
         audit_op code;
+        struct inode * inode = NULL;
         __u64 mask = 0;
         int rc = 0;
         
@@ -191,15 +207,18 @@ int smfs_audit_check(struct inode * parent, hook_op hook, int ret,
         if (hook == HOOK_SPECIAL) { 
                 struct audit_info * info = msg;
                 code = info->m.code;
+                inode = info->child;
         }
-        else
+        else {
+                inode = get_inode_from_hook(hook, msg);
                 code = hook2audit(hook);
-
-        rc = smfs_get_audit(parent->i_sb, parent,
-                            get_inode_from_hook(hook, msg),
-                            &mask);
+        }
+        
+        rc = smfs_get_audit(parent->i_sb, parent, inode, &mask);
+        
         if (rc < 0)
                 RETURN(0);
+
         //should only failures be audited?
         if (ret >= 0 && IS_AUDIT_OP(mask, AUDIT_FAIL))
                 RETURN(0); 
@@ -259,14 +278,40 @@ int smfs_set_audit(struct super_block * sb, struct inode * inode,
 {
         void * handle = NULL;
         struct fsfilt_operations * fsfilt = S2SMI(sb)->sm_fsfilt;
+        struct smfs_inode_info *smi = NULL;
         int rc = 0;
+        struct audit_priv *priv;
+        
+        priv = smfs_get_plg_priv(S2SMI(sb), SMFS_PLG_AUDIT);
         
         ENTRY;
         
+        if (IS_AUDIT_OP((*mask), AUDIT_SYNC)) {
+                struct audit_priv *priv;
+                
+                priv = smfs_get_plg_priv(S2SMI(sb), SMFS_PLG_AUDIT);
+                if (priv)
+                        audit_notify(priv->audit_ctxt->loc_handle, NULL, 1);
+                //to wait for flush
+                return audit_notify(NULL, NULL, 1);
+        }
+        
+        if (IS_AUDIT_OP((*mask), AUDIT_NULL)) {
+                if (priv)
+                        priv->audit_null ^= 1;
+                return 0;
+        }
+
         if (IS_AUDIT_OP((*mask), AUDIT_FS))
                 return smfs_set_fs_audit(sb, mask);
 
         LASSERT(inode);
+        smi = I2SMI(inode);
+        /* save audit EA in inode_info */
+        if (rc >= 0) {
+                smi->au_info.au_mask = *mask;
+                smi->au_info.au_valid = 1;
+        }
         
         handle = fsfilt->fs_start(inode, FSFILT_OP_SETATTR, NULL, 0);
         if (IS_ERR(handle))
@@ -275,7 +320,6 @@ int smfs_set_audit(struct super_block * sb, struct inode * inode,
         if (fsfilt->fs_set_xattr)
                 rc = fsfilt->fs_set_xattr(inode, handle, AUDIT_ATTR_EA,
                                           mask, sizeof(*mask));
-
         fsfilt->fs_commit(inode->i_sb, inode, handle, 1);
         RETURN(rc);
                                 
@@ -333,8 +377,10 @@ static int smfs_audit_post_op(hook_op code, struct inode * inode, void * msg,
         if (rc != 0) {
                 CERROR("Error adding audit record: %d\n", rc);
                 rc= -EINVAL;
-        } else {
-                audit_notify(priv->audit_ctxt->loc_handle, priv->au_id2name);
+        /* delay notify for create op */
+        } else if (!(code == HOOK_CREATE && ret == 0)) { 
+                audit_notify(priv->audit_ctxt->loc_handle, priv->au_id2name,
+                             priv->audit_null);
         }
         
         OBD_FREE(buffer, PAGE_SIZE);
@@ -392,6 +438,7 @@ static int smfs_start_audit(struct super_block *sb, void *arg,
         }
         //read fs audit settings if any
        audit_p->a_mask = AUDIT_OFF;
+        audit_p->audit_null = 0;
 
         f = filp_open(AUDIT_ATTR_FILE, O_RDONLY, 0644);
         if (!IS_ERR(f)) {
@@ -550,25 +597,31 @@ int audit_client_log(struct super_block * sb, struct audit_msg * msg)
         
         llh = (void*)buffer;
         llh->lrh_type = SMFS_AUDIT_GEN_REC;
-        pbuf = buffer + sizeof(*llh);
 
         //fill common fields
-        rec = (void*)(pbuf);
+        rec = (void*)buffer + sizeof(*llh);
         rec->opcode = msg->code;
         rec->result = msg->result;
         rec->uid = msg->uid;
         rec->gid = msg->gid;
         rec->nid = msg->nid;
         rec->time = cur_time.tv_sec * USEC_PER_SEC + cur_time.tv_usec;
-        pbuf += sizeof(*rec);
-        
+        len = sizeof(*rec);
+        pbuf = (char*)rec + len;
+
+        CDEBUG(D_VFSTRACE, "AUDITLOG:"DLID4"\n", OLID4(&msg->id));
+        /* check id is valid */
+        LASSERT(id_ino(&msg->id));
+        LASSERT(id_fid(&msg->id));
+        //LASSERT(id_type(&msg->id) & S_IFMT);
+
         switch (msg->code) {
                 case AUDIT_READ:    
                 case AUDIT_WRITE:
                 case AUDIT_MMAP:
                 case AUDIT_OPEN:
                 case AUDIT_STAT:
-                        len = audit_rec_from_id(&pbuf, &msg->id);
+                        len += audit_rec_from_id(&pbuf, &msg->id);
                         break;
                 default:
                         CERROR("Unknown code %i in audit_msg\n", msg->code);
@@ -581,7 +634,7 @@ int audit_client_log(struct super_block * sb, struct audit_msg * msg)
                 CERROR("Error adding audit client record: %d\n", rc);
                 rc= -EINVAL;
         } else {
-                audit_notify(ll_handle, priv->au_id2name);
+                audit_notify(ll_handle, priv->au_id2name, priv->audit_null);
         }
         
         OBD_FREE(buffer, PAGE_SIZE);