Whamcloud - gitweb
add null_audit command to lctl which will make audit silent. For testing purposes.
[fs/lustre-release.git] / lustre / smfs / audit.c
1 /* -*- mode: c; c-basic-offset: 8; indent-tabs-mode: nil; -*-
2  * vim:expandtab:shiftwidth=8:tabstop=8:
3  *
4  *  lustre/smfs/audit_mds.c
5  *  Lustre filesystem audit part for MDS
6  *
7  *  Copyright (C) 2004 Cluster File Systems, Inc.
8  *
9  *   This file is part of Lustre, http://www.lustre.org.
10  *
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.
14  *
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.
19  *
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.
23  */
24 #ifndef EXPORT_SYMTAB
25 # define EXPORT_SYMTAB
26 #endif
27
28 #define DEBUG_SUBSYSTEM S_SM
29
30 #include <linux/kmod.h>
31 #include <linux/init.h>
32 #include <linux/fs.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"
43
44 static audit_op hook2audit(hook_op hook)
45 {
46         audit_op opcode = AUDIT_UNKNOWN;
47
48         switch (hook) 
49         {
50                 case HOOK_CREATE:
51                 case HOOK_SYMLINK:
52                 case HOOK_MKDIR:
53                 case HOOK_MKNOD:
54                         return AUDIT_CREATE;
55                         
56                 case HOOK_LINK:
57                         return AUDIT_LINK;
58                                                 
59                 case HOOK_RMDIR:
60                 case HOOK_UNLINK:
61                         return AUDIT_UNLINK;
62                         
63                 case HOOK_READLINK:
64                         return AUDIT_READLINK;
65                         
66                 case HOOK_RENAME:
67                         return AUDIT_RENAME;
68                         
69                 case HOOK_SETATTR:
70                 case HOOK_F_SETATTR:
71                         return AUDIT_SETATTR;
72                         
73                 case HOOK_SI_WRITE:
74                 case HOOK_WRITE:
75                         return AUDIT_WRITE;
76                         
77                 case HOOK_SI_READ:
78                 case HOOK_READ:
79                         return AUDIT_READ;
80
81                 case HOOK_READDIR:
82                         return AUDIT_READDIR;
83
84                 default:
85                         break;
86         }
87         
88         return opcode;
89 }
90
91 struct inode * get_inode_from_hook(hook_op hook, void * msg) 
92 {
93         struct inode * inode;
94         
95         switch (hook)
96         {
97                 case HOOK_LINK:
98                 {
99                         struct hook_link_msg * m = msg;
100                         inode = m->dentry->d_inode;
101                         break;
102                 }
103                 case HOOK_UNLINK:
104                 case HOOK_RMDIR:
105                 {
106                         struct hook_unlink_msg * m = msg;
107                         inode = m->dentry->d_inode;
108                         break;
109                 }
110                 case HOOK_READLINK:
111                 {
112                         struct hook_symlink_msg * m = msg;
113                         inode = m->dentry->d_inode;
114                         break;
115                 }        
116                 case HOOK_RENAME:
117                 {
118                         struct hook_rename_msg * m = msg;
119                         inode = m->dentry->d_inode;
120                         break;
121                 }        
122                 default:
123                         inode = NULL;
124         }
125
126         return inode;
127 }
128
129 static inline int smfs_get_inode_audit(struct inode *inode, __u64 *mask)
130 {
131         struct fsfilt_operations *fsfilt = S2SMI(inode->i_sb)->sm_cache_fsfilt;
132         struct smfs_inode_info * smi = I2SMI(inode);
133         int rc = 0;
134         
135         /* omit __iopen__ dir */
136         if (inode->i_ino == SMFS_IOPEN_INO) {
137                 *mask = AUDIT_OFF;
138                 RETURN(-ENOENT);
139         }
140         if (smi->au_info.au_valid)
141                 *mask = smi->au_info.au_mask;
142         else {
143                 rc = fsfilt->fs_get_xattr(I2CI(inode), AUDIT_ATTR_EA,
144                                           mask, sizeof(*mask));
145                 if (rc <= 0)
146                         *mask = AUDIT_OFF;
147                 smi->au_info.au_valid = 1;
148                 smi->au_info.au_mask = *mask;
149         }
150         RETURN(0);
151 }
152
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)
156 {
157         struct smfs_super_info * smb = S2SMI(sb);
158         struct obd_device * obd = smb->smsi_exp->exp_obd;
159         struct audit_priv * priv = NULL;
160         
161         ENTRY;
162         
163         if (!SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT))
164                 RETURN(-EINVAL);
165         
166         priv = smfs_get_plg_priv(S2SMI(sb), SMFS_PLG_AUDIT);
167               
168         if (!priv)
169                 RETURN(-ENOENT);
170         
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))
175                         RETURN(-EINVAL);
176                 (*mask) = priv->a_mask;
177                 RETURN(0);
178         }
179         
180         /* get inode audit EA */
181         if (parent) {
182                 smfs_get_inode_audit(parent, mask);
183                 /* check if parent has audit */
184                 if (IS_AUDIT(*mask))
185                         RETURN(0);
186         }
187         
188         if (inode) {
189                 smfs_get_inode_audit(inode, mask);
190                 if (IS_AUDIT(*mask))
191                         RETURN(0);
192         }
193
194         RETURN(-ENODATA);
195 }
196
197 int smfs_audit_check(struct inode * parent, hook_op hook, int ret,
198                      struct audit_priv * priv, void * msg)
199 {
200         audit_op code;
201         struct inode * inode = NULL;
202         __u64 mask = 0;
203         int rc = 0;
204         
205         ENTRY;
206
207         if (hook == HOOK_SPECIAL) { 
208                 struct audit_info * info = msg;
209                 code = info->m.code;
210                 inode = info->child;
211         }
212         else {
213                 inode = get_inode_from_hook(hook, msg);
214                 code = hook2audit(hook);
215         }
216         
217         rc = smfs_get_audit(parent->i_sb, parent, inode, &mask);
218         
219         if (rc < 0)
220                 RETURN(0);
221
222         //should only failures be audited?
223         if (ret >= 0 && IS_AUDIT_OP(mask, AUDIT_FAIL))
224                 RETURN(0); 
225
226         //check audit mask
227         RETURN(IS_AUDIT_OP(mask, code));
228 }
229
230 static int smfs_set_fs_audit (struct super_block * sb, __u64 *mask)
231 {
232         struct smfs_super_info * smb = S2SMI(sb);
233         struct fsfilt_operations * fsfilt = smb->sm_fsfilt;
234         int rc = 0;
235         loff_t off = 0;
236         struct file * f = NULL;
237         struct audit_priv *priv;
238         struct lvfs_run_ctxt * ctxt, saved;
239         ENTRY;
240         
241         ctxt = &smb->smsi_exp->exp_obd->obd_lvfs_ctxt;
242         
243         priv = smfs_get_plg_priv(smb, SMFS_PLG_AUDIT);
244         if(!priv) {
245                 CERROR("Audit is not initialized, use mountoptions 'audit'\n");
246                 RETURN(-EINVAL);
247         }
248         
249         push_ctxt(&saved, ctxt, NULL);
250
251         f = filp_open(AUDIT_ATTR_FILE, O_RDWR|O_CREAT, 0600);
252         if (IS_ERR(f)) {
253                 CERROR("cannot get audit_setting file\n");
254                 rc = -EINVAL;
255                 goto exit;
256         }
257                 
258         rc = fsfilt->fs_write_record(f, mask, sizeof(*mask), &off, 1);
259         if (rc) {
260                 CERROR("error writting audit setting: rc = %d\n", rc);
261                 goto exit;
262         }
263         
264         priv->a_mask = (*mask);
265         
266 exit:
267         if (f)
268                 filp_close(f, 0);
269
270         pop_ctxt(&saved, ctxt, NULL);
271
272         RETURN (rc);
273 }
274
275 //set audit attributes for directory/file
276 int smfs_set_audit(struct super_block * sb, struct inode * inode,
277                    __u64 * mask)
278 {
279         void * handle = NULL;
280         struct fsfilt_operations * fsfilt = S2SMI(sb)->sm_fsfilt;
281         struct smfs_inode_info *smi = NULL;
282         int rc = 0;
283         struct audit_priv *priv;
284         
285         priv = smfs_get_plg_priv(S2SMI(sb), SMFS_PLG_AUDIT);
286         
287         ENTRY;
288         
289         if (IS_AUDIT_OP((*mask), AUDIT_SYNC)) {
290                 struct audit_priv *priv;
291                 
292                 priv = smfs_get_plg_priv(S2SMI(sb), SMFS_PLG_AUDIT);
293                 if (priv)
294                         audit_notify(priv->audit_ctxt->loc_handle, NULL, 1);
295                 //to wait for flush
296                 return audit_notify(NULL, NULL, 1);
297         }
298         
299         if (IS_AUDIT_OP((*mask), AUDIT_NULL)) {
300                 if (priv)
301                         priv->audit_null ^= 1;
302                 return 0;
303         }
304
305         if (IS_AUDIT_OP((*mask), AUDIT_FS))
306                 return smfs_set_fs_audit(sb, mask);
307
308         LASSERT(inode);
309         smi = I2SMI(inode);
310         /* save audit EA in inode_info */
311         if (rc >= 0) {
312                 smi->au_info.au_mask = *mask;
313                 smi->au_info.au_valid = 1;
314         }
315         
316         handle = fsfilt->fs_start(inode, FSFILT_OP_SETATTR, NULL, 0);
317         if (IS_ERR(handle))
318                 RETURN(PTR_ERR(handle));
319         
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);
324         RETURN(rc);
325                                 
326 }
327
328 static int smfs_audit_post_op(hook_op code, struct inode * inode, void * msg,
329                               int ret, void * arg)
330 {
331         int rc = 0, len;
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;
338
339         //check that we are in lustre ctxt
340         if (!SMFS_IS(I2SMI(inode)->smi_flags, SMFS_PLG_AUDIT))
341                 return 0;
342         
343         if (!handler || !handler[code])
344                 return 0;
345         
346         if (smfs_audit_check(inode, code, ret, priv, msg) == 0)
347                 return 0;
348
349         ENTRY;
350         
351         do_gettimeofday(&cur_time);
352
353         OBD_ALLOC(buffer, PAGE_SIZE);
354         if (!buffer)
355                 RETURN(-ENOMEM);
356         
357         llh = (void*)buffer;
358         //fill common fields
359         rec = (void*)(buffer + sizeof(*llh));
360                
361         rec->result = ret;
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;
366         
367         len = handler[code](inode, msg, priv, (char*)rec,
368                                            &llh->lrh_type);
369         
370         LASSERT(llh->lrh_type == SMFS_AUDIT_GEN_REC ||
371                 llh->lrh_type == SMFS_AUDIT_NAME_REC);
372
373         llh->lrh_len = size_round(len);
374
375         rc = llog_cat_add_rec(priv->audit_ctxt->loc_handle, llh, NULL,
376                               (void*)rec, NULL, NULL); 
377         if (rc != 0) {
378                 CERROR("Error adding audit record: %d\n", rc);
379                 rc= -EINVAL;
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,
383                              priv->audit_null);
384         }
385         
386         OBD_FREE(buffer, PAGE_SIZE);
387         
388         RETURN(rc);
389 }
390
391 /* Helpers */
392 static int smfs_trans_audit (struct super_block *sb, void *arg,
393                            struct audit_priv * priv)
394 {
395         int size = 1; //one record in log per operation.
396
397         return size;
398 }
399
400 extern int mds_alloc_inode_ids(struct obd_device *, struct inode *,
401                         void *, struct lustre_id *, struct lustre_id *);
402
403 static int smfs_start_audit(struct super_block *sb, void *arg,
404                           struct audit_priv * audit_p)
405 {
406         struct smfs_super_info * smb = S2SMI(sb);
407         struct fsfilt_operations * fsfilt = smb->sm_fsfilt;
408         struct obd_device *obd = arg;
409         struct file * f;
410         int rc = 0;
411
412         ENTRY;
413
414         //is plugin already activated
415         if (SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT))
416                 RETURN(0);
417         
418         rc = audit_start_transferd();
419         if (rc) {
420                 CERROR("can't start audit transfer daemon. rc:%d\n", rc);
421                 RETURN(rc);
422         }
423         
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);
428                 }
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);
432                 }
433                 else {
434                         CDEBUG(D_INODE, "Unknown obd type %s\n",
435                                obd->obd_type->typ_name);       
436                         RETURN(0);
437                 }
438         }
439         //read fs audit settings if any
440         audit_p->a_mask = AUDIT_OFF;
441         audit_p->audit_null = 0;
442
443         f = filp_open(AUDIT_ATTR_FILE, O_RDONLY, 0644);
444         if (!IS_ERR(f)) {
445                 loff_t off = 0;
446                 rc = fsfilt->fs_read_record(f, &audit_p->a_mask, 
447                                         sizeof(audit_p->a_mask), &off);
448                 if (rc) {
449                         CERROR("error reading audit setting: rc = %d\n", rc);
450                 }
451                 filp_close(f, 0);
452         }
453         
454         SMFS_SET(smb->plg_flags, SMFS_PLG_AUDIT);
455
456         RETURN(0);
457 }
458
459 int smfs_stop_audit(struct super_block *sb, void *arg,
460                   struct audit_priv * audit_p)
461 {
462         struct smfs_super_info * smb = S2SMI(sb);
463         struct llog_ctxt *ctxt = audit_p->audit_ctxt;
464         ENTRY;
465
466         if (!SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT))
467                 RETURN(0);
468
469         audit_stop_transferd();
470
471         SMFS_CLEAR(smb->plg_flags, SMFS_PLG_AUDIT);
472
473         if (ctxt->loc_llogs)
474                 ctxt->loc_llogs->llog_ctxt[LLOG_AUDIT_ORIG_CTXT] = NULL;
475
476         llog_catalog_cleanup(ctxt);
477         OBD_FREE(ctxt, sizeof(*ctxt));
478         audit_p->audit_ctxt = NULL;
479         
480         RETURN(0);
481 }
482
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;
488         }
489                          
490         return 0;
491 }
492
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,
501 };
502
503 static int smfs_audit_help_op(int code, struct super_block * sb,
504                             void * arg, void * priv)
505 {
506         int rc = 0;
507         
508         if (smfs_audit_helpers[code])
509                 rc = smfs_audit_helpers[code](sb, arg, (struct audit_priv *) priv);
510         return rc;
511 }
512
513 static int smfs_exit_audit(struct super_block *sb, 
514                            void * arg)
515 {
516         struct audit_priv * priv = arg;
517         struct smfs_plugin * plg;
518         ENTRY;
519
520         plg = smfs_deregister_plugin(sb, SMFS_PLG_AUDIT);
521         if (plg)
522                 OBD_FREE(plg, sizeof(*plg));
523         else
524                 CERROR("Cannot find AUDIT plugin while unregistering\n");
525         
526         if (priv)
527                 OBD_FREE(priv, sizeof(*priv));
528         
529         RETURN(0);
530 }
531
532 int smfs_init_audit(struct super_block *sb)
533 {
534         int rc = 0;
535         struct audit_priv * priv = NULL;
536         struct smfs_plugin * plg = NULL;
537
538         ENTRY;
539         
540         OBD_ALLOC(plg, sizeof(*plg));
541         if (!plg) {
542                 rc = -ENOMEM;
543                 goto exit;
544         }
545         
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;
550
551         OBD_ALLOC(priv, sizeof(*priv));
552         if (!priv) {
553                 rc = -ENOMEM;
554                 goto exit;
555         }
556
557         plg->plg_private = priv;
558         rc = smfs_register_plugin(sb, plg);
559         if (!rc)
560                 RETURN(0);
561 exit:
562         if (priv)
563                 OBD_FREE(priv, sizeof(*priv));
564         
565         if (plg)
566                 OBD_FREE(plg, sizeof(*plg));
567
568         RETURN(rc);
569
570 }
571
572 int audit_client_log(struct super_block * sb, struct audit_msg * msg)
573 {
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;
579         int len = 0, rc = 0;
580         struct timeval cur_time;
581         //char name[32];
582         struct audit_priv * priv;
583         
584         ENTRY;
585         
586         do_gettimeofday(&cur_time);
587         
588         priv = smfs_get_plg_priv(smb, SMFS_PLG_AUDIT);
589         if (!priv)
590                 RETURN(-EINVAL);
591         
592         ll_handle = priv->audit_ctxt->loc_handle;
593         
594         OBD_ALLOC(buffer, PAGE_SIZE);
595         if (!buffer)
596                 RETURN(-ENOMEM);
597         
598         llh = (void*)buffer;
599         llh->lrh_type = SMFS_AUDIT_GEN_REC;
600
601         //fill common fields
602         rec = (void*)buffer + sizeof(*llh);
603         rec->opcode = msg->code;
604         rec->result = msg->result;
605         rec->uid = msg->uid;
606         rec->gid = msg->gid;
607         rec->nid = msg->nid;
608         rec->time = cur_time.tv_sec * USEC_PER_SEC + cur_time.tv_usec;
609         len = sizeof(*rec);
610         pbuf = (char*)rec + len;
611
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);
617
618         switch (msg->code) {
619                 case AUDIT_READ:    
620                 case AUDIT_WRITE:
621                 case AUDIT_MMAP:
622                 case AUDIT_OPEN:
623                 case AUDIT_STAT:
624                         len += audit_rec_from_id(&pbuf, &msg->id);
625                         break;
626                 default:
627                         CERROR("Unknown code %i in audit_msg\n", msg->code);
628         }
629         
630         llh->lrh_len = size_round(len);
631
632         rc = llog_cat_add_rec(ll_handle, llh, NULL, (void*)rec, NULL, NULL);
633         if (rc != 0) {
634                 CERROR("Error adding audit client record: %d\n", rc);
635                 rc= -EINVAL;
636         } else {
637                 audit_notify(ll_handle, priv->au_id2name, priv->audit_null);
638         }
639         
640         OBD_FREE(buffer, PAGE_SIZE);
641         return rc;
642 }
643