1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=8:tabstop=8:
4 * lustre/smfs/audit_mds.c
5 * Lustre filesystem audit part for MDS
7 * Copyright (C) 2004 Cluster File Systems, Inc.
9 * This file is part of Lustre, http://www.lustre.org.
11 * Lustre is free software; you can redistribute it and/or
12 * modify it under the terms of version 2 of the GNU General Public
13 * License as published by the Free Software Foundation.
15 * Lustre is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with Lustre; if not, write to the Free Software
22 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 # define EXPORT_SYMTAB
28 #define DEBUG_SUBSYSTEM S_SM
30 #include <linux/kmod.h>
31 #include <linux/init.h>
33 #include <linux/slab.h>
34 #include <linux/obd_class.h>
35 #include <linux/obd_support.h>
36 #include <linux/lustre_lib.h>
37 #include <linux/lustre_idl.h>
38 #include <linux/lustre_fsfilt.h>
39 #include <linux/lustre_smfs.h>
40 #include <linux/lustre_audit.h>
41 #include <linux/lustre_log.h>
42 #include "smfs_internal.h"
44 static audit_op hook2audit(hook_op hook)
46 audit_op opcode = AUDIT_UNKNOWN;
64 return AUDIT_READLINK;
91 struct inode * get_inode_from_hook(hook_op hook, void * msg)
99 struct hook_link_msg * m = msg;
100 inode = m->dentry->d_inode;
106 struct hook_unlink_msg * m = msg;
107 inode = m->dentry->d_inode;
112 struct hook_symlink_msg * m = msg;
113 inode = m->dentry->d_inode;
118 struct hook_rename_msg * m = msg;
119 inode = m->dentry->d_inode;
129 static inline int smfs_get_inode_audit(struct inode *inode, __u64 *mask)
131 struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_cache_fsfilt;
132 struct smfs_inode_info * smi = I2SMI(inode);
135 /* omit __iopen__ dir */
136 if (inode->i_ino == SMFS_IOPEN_INO) {
140 if (smi->au_info.au_valid)
141 *mask = smi->au_info.au_mask;
143 rc = fsfilt->fs_get_xattr(I2CI(inode), AUDIT_ATTR_EA,
144 mask, sizeof(*mask));
147 smi->au_info.au_valid = 1;
148 smi->au_info.au_mask = *mask;
153 /* is called also from fsfilt_smfs_get_info */
154 int smfs_get_audit(struct super_block * sb, struct inode * parent,
155 struct inode * inode, __u64 * mask)
157 struct smfs_super_info * smb = S2SMI(sb);
158 struct obd_device * obd = smb->smsi_exp->exp_obd;
159 struct audit_priv * priv = NULL;
163 if (!SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT))
166 priv = smfs_get_plg_priv(S2SMI(sb), SMFS_PLG_AUDIT);
171 if (IS_AUDIT(priv->a_mask)) {
172 /* no audit for directories on OSS */
173 if (inode && S_ISDIR(inode->i_mode) &&
174 !strcmp(obd->obd_type->typ_name, OBD_FILTER_DEVICENAME))
176 (*mask) = priv->a_mask;
180 /* get inode audit EA */
182 smfs_get_inode_audit(parent, mask);
183 /* check if parent has audit */
189 smfs_get_inode_audit(inode, mask);
197 int smfs_audit_check(struct inode * parent, hook_op hook, int ret,
198 struct audit_priv * priv, void * msg)
201 struct inode * inode = NULL;
207 if (hook == HOOK_SPECIAL) {
208 struct audit_info * info = msg;
213 inode = get_inode_from_hook(hook, msg);
214 code = hook2audit(hook);
217 rc = smfs_get_audit(parent->i_sb, parent, inode, &mask);
222 //should only failures be audited?
223 if (ret >= 0 && IS_AUDIT_OP(mask, AUDIT_FAIL))
227 RETURN(IS_AUDIT_OP(mask, code));
230 static int smfs_set_fs_audit (struct super_block * sb, __u64 *mask)
232 struct smfs_super_info * smb = S2SMI(sb);
233 struct fsfilt_operations * fsfilt = smb->sm_fsfilt;
236 struct file * f = NULL;
237 struct audit_priv *priv;
238 struct lvfs_run_ctxt * ctxt, saved;
241 ctxt = &smb->smsi_exp->exp_obd->obd_lvfs_ctxt;
243 priv = smfs_get_plg_priv(smb, SMFS_PLG_AUDIT);
245 CERROR("Audit is not initialized, use mountoptions 'audit'\n");
249 push_ctxt(&saved, ctxt, NULL);
251 f = filp_open(AUDIT_ATTR_FILE, O_RDWR|O_CREAT, 0600);
253 CERROR("cannot get audit_setting file\n");
258 rc = fsfilt->fs_write_record(f, mask, sizeof(*mask), &off, 1);
260 CERROR("error writting audit setting: rc = %d\n", rc);
264 priv->a_mask = (*mask);
270 pop_ctxt(&saved, ctxt, NULL);
275 //set audit attributes for directory/file
276 int smfs_set_audit(struct super_block * sb, struct inode * inode,
279 void * handle = NULL;
280 struct fsfilt_operations * fsfilt = S2SMI(sb)->sm_fsfilt;
281 struct smfs_inode_info *smi = NULL;
283 struct audit_priv *priv;
285 priv = smfs_get_plg_priv(S2SMI(sb), SMFS_PLG_AUDIT);
289 if (IS_AUDIT_OP((*mask), AUDIT_SYNC)) {
290 struct audit_priv *priv;
292 priv = smfs_get_plg_priv(S2SMI(sb), SMFS_PLG_AUDIT);
294 audit_notify(priv->audit_ctxt->loc_handle, NULL, 1);
296 return audit_notify(NULL, NULL, 1);
299 if (IS_AUDIT_OP((*mask), AUDIT_NULL)) {
301 priv->audit_null ^= 1;
305 if (IS_AUDIT_OP((*mask), AUDIT_FS))
306 return smfs_set_fs_audit(sb, mask);
310 /* save audit EA in inode_info */
312 smi->au_info.au_mask = *mask;
313 smi->au_info.au_valid = 1;
316 handle = fsfilt->fs_start(inode, FSFILT_OP_SETATTR, NULL, 0);
318 RETURN(PTR_ERR(handle));
320 if (fsfilt->fs_set_xattr)
321 rc = fsfilt->fs_set_xattr(inode, handle, AUDIT_ATTR_EA,
322 mask, sizeof(*mask));
323 fsfilt->fs_commit(inode->i_sb, inode, handle, 1);
328 static int smfs_audit_post_op(hook_op code, struct inode * inode, void * msg,
332 char * buffer = NULL;
333 struct audit_record * rec = NULL;
334 struct llog_rec_hdr * llh;
335 struct timeval cur_time;
336 struct audit_priv * priv = arg;
337 audit_get_op * handler = priv->audit_get_record;
339 //check that we are in lustre ctxt
340 if (!SMFS_IS(I2SMI(inode)->smi_flags, SMFS_PLG_AUDIT))
343 if (!handler || !handler[code])
346 if (smfs_audit_check(inode, code, ret, priv, msg) == 0)
351 do_gettimeofday(&cur_time);
353 OBD_ALLOC(buffer, PAGE_SIZE);
359 rec = (void*)(buffer + sizeof(*llh));
362 rec->uid = current->uid;
363 rec->gid = current->gid;
364 rec->nid = current->user->nid;
365 rec->time = cur_time.tv_sec * USEC_PER_SEC + cur_time.tv_usec;
367 len = handler[code](inode, msg, priv, (char*)rec,
370 LASSERT(llh->lrh_type == SMFS_AUDIT_GEN_REC ||
371 llh->lrh_type == SMFS_AUDIT_NAME_REC);
373 llh->lrh_len = size_round(len);
375 rc = llog_cat_add_rec(priv->audit_ctxt->loc_handle, llh, NULL,
376 (void*)rec, NULL, NULL);
378 CERROR("Error adding audit record: %d\n", rc);
380 /* delay notify for create op */
381 } else if (!(code == HOOK_CREATE && ret == 0)) {
382 audit_notify(priv->audit_ctxt->loc_handle, priv->au_id2name,
386 OBD_FREE(buffer, PAGE_SIZE);
392 static int smfs_trans_audit (struct super_block *sb, void *arg,
393 struct audit_priv * priv)
395 int size = 1; //one record in log per operation.
400 extern int mds_alloc_inode_ids(struct obd_device *, struct inode *,
401 void *, struct lustre_id *, struct lustre_id *);
403 static int smfs_start_audit(struct super_block *sb, void *arg,
404 struct audit_priv * audit_p)
406 struct smfs_super_info * smb = S2SMI(sb);
407 struct fsfilt_operations * fsfilt = smb->sm_fsfilt;
408 struct obd_device *obd = arg;
414 //is plugin already activated
415 if (SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT))
418 rc = audit_start_transferd();
420 CERROR("can't start audit transfer daemon. rc:%d\n", rc);
424 if (obd && obd->obd_type && obd->obd_type->typ_name) {
425 if (!strcmp(obd->obd_type->typ_name, "mds")) {
426 CDEBUG(D_INODE, "Setup MDS audit handler\n");
427 audit_mds_setup(obd, sb, audit_p);
429 else if (!strcmp(obd->obd_type->typ_name, "obdfilter")) {
430 CDEBUG(D_INODE, "Setup OST audit handler\n");
431 audit_ost_setup(obd, sb, audit_p);
434 CDEBUG(D_INODE, "Unknown obd type %s\n",
435 obd->obd_type->typ_name);
439 //read fs audit settings if any
440 audit_p->a_mask = AUDIT_OFF;
441 audit_p->audit_null = 0;
443 f = filp_open(AUDIT_ATTR_FILE, O_RDONLY, 0644);
446 rc = fsfilt->fs_read_record(f, &audit_p->a_mask,
447 sizeof(audit_p->a_mask), &off);
449 CERROR("error reading audit setting: rc = %d\n", rc);
454 SMFS_SET(smb->plg_flags, SMFS_PLG_AUDIT);
459 int smfs_stop_audit(struct super_block *sb, void *arg,
460 struct audit_priv * audit_p)
462 struct smfs_super_info * smb = S2SMI(sb);
463 struct llog_ctxt *ctxt = audit_p->audit_ctxt;
466 if (!SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT))
469 audit_stop_transferd();
471 SMFS_CLEAR(smb->plg_flags, SMFS_PLG_AUDIT);
474 ctxt->loc_llogs->llog_ctxt[LLOG_AUDIT_ORIG_CTXT] = NULL;
476 llog_catalog_cleanup(ctxt);
477 OBD_FREE(ctxt, sizeof(*ctxt));
478 audit_p->audit_ctxt = NULL;
483 int smfs_audit_set_info(struct super_block *sb, void *arg,
484 struct audit_priv *priv) {
485 struct plg_info_msg * msg = arg;
486 if (KEY_IS(msg->key, "id2name")) {
487 priv->au_id2name = msg->val;
493 typedef int (*audit_helper)(struct super_block * sb, void *msg, struct audit_priv *);
494 static audit_helper smfs_audit_helpers[PLG_HELPER_MAX] = {
495 [PLG_START] smfs_start_audit,
496 [PLG_STOP] smfs_stop_audit,
497 [PLG_TRANS_SIZE] smfs_trans_audit,
498 [PLG_TEST_INODE] NULL,
499 [PLG_SET_INODE] NULL,
500 [PLG_SET_INFO] smfs_audit_set_info,
503 static int smfs_audit_help_op(int code, struct super_block * sb,
504 void * arg, void * priv)
508 if (smfs_audit_helpers[code])
509 rc = smfs_audit_helpers[code](sb, arg, (struct audit_priv *) priv);
513 static int smfs_exit_audit(struct super_block *sb,
516 struct audit_priv * priv = arg;
517 struct smfs_plugin * plg;
520 plg = smfs_deregister_plugin(sb, SMFS_PLG_AUDIT);
522 OBD_FREE(plg, sizeof(*plg));
524 CERROR("Cannot find AUDIT plugin while unregistering\n");
527 OBD_FREE(priv, sizeof(*priv));
532 int smfs_init_audit(struct super_block *sb)
535 struct audit_priv * priv = NULL;
536 struct smfs_plugin * plg = NULL;
540 OBD_ALLOC(plg, sizeof(*plg));
546 plg->plg_type = SMFS_PLG_AUDIT;
547 plg->plg_post_op = &smfs_audit_post_op;
548 plg->plg_helper = &smfs_audit_help_op;
549 plg->plg_exit = &smfs_exit_audit;
551 OBD_ALLOC(priv, sizeof(*priv));
557 plg->plg_private = priv;
558 rc = smfs_register_plugin(sb, plg);
563 OBD_FREE(priv, sizeof(*priv));
566 OBD_FREE(plg, sizeof(*plg));
572 int audit_client_log(struct super_block * sb, struct audit_msg * msg)
574 struct smfs_super_info * smb = S2SMI(sb);
575 char *buffer = NULL, *pbuf = NULL;
576 struct audit_record * rec = NULL;
577 struct llog_rec_hdr * llh;
578 struct llog_handle * ll_handle = NULL;
580 struct timeval cur_time;
582 struct audit_priv * priv;
586 do_gettimeofday(&cur_time);
588 priv = smfs_get_plg_priv(smb, SMFS_PLG_AUDIT);
592 ll_handle = priv->audit_ctxt->loc_handle;
594 OBD_ALLOC(buffer, PAGE_SIZE);
599 llh->lrh_type = SMFS_AUDIT_GEN_REC;
602 rec = (void*)buffer + sizeof(*llh);
603 rec->opcode = msg->code;
604 rec->result = msg->result;
608 rec->time = cur_time.tv_sec * USEC_PER_SEC + cur_time.tv_usec;
610 pbuf = (char*)rec + len;
612 CDEBUG(D_VFSTRACE, "AUDITLOG:"DLID4"\n", OLID4(&msg->id));
613 /* check id is valid */
614 LASSERT(id_ino(&msg->id));
615 LASSERT(id_fid(&msg->id));
616 //LASSERT(id_type(&msg->id) & S_IFMT);
624 len += audit_rec_from_id(&pbuf, &msg->id);
627 CERROR("Unknown code %i in audit_msg\n", msg->code);
630 llh->lrh_len = size_round(len);
632 rc = llog_cat_add_rec(ll_handle, llh, NULL, (void*)rec, NULL, NULL);
634 CERROR("Error adding audit client record: %d\n", rc);
637 audit_notify(ll_handle, priv->au_id2name, priv->audit_null);
640 OBD_FREE(buffer, PAGE_SIZE);