static audit_op hook2audit(hook_op hook)
{
- audit_op opcode = AUDIT_NONE;
+ audit_op opcode = AUDIT_UNKNOWN;
switch (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;
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;
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);
(*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);
}
struct audit_priv * priv, void * msg)
{
audit_op code;
+ struct inode * inode = NULL;
__u64 mask = 0;
int rc = 0;
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);
{
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))
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);
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);
}
//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)) {
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);
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);