Whamcloud - gitweb
- don't call obd_set_info() on the NULL mdc export on rename.
[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_NONE;
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                         return AUDIT_WRITE;
75                         
76                 case HOOK_SI_READ:
77                         return AUDIT_READ;
78
79                 case HOOK_READDIR:
80                         return AUDIT_READDIR;
81
82                 default:
83                         return AUDIT_NONE;
84         }
85         
86         return opcode;
87 }
88
89 struct inode * get_inode_from_hook(hook_op hook, void * msg) 
90 {
91         struct inode * inode;
92         
93         switch (hook)
94         {
95                 case HOOK_LINK:
96                 {
97                         struct hook_link_msg * m = msg;
98                         inode = m->dentry->d_inode;
99                         break;
100                 }
101                 case HOOK_UNLINK:
102                 case HOOK_RMDIR:
103                 {
104                         struct hook_unlink_msg * m = msg;
105                         inode = m->dentry->d_inode;
106                         break;
107                 }
108                 case HOOK_READLINK:
109                 {
110                         struct hook_symlink_msg * m = msg;
111                         inode = m->dentry->d_inode;
112                         break;
113                 }        
114                 case HOOK_RENAME:
115                 {
116                         struct hook_rename_msg * m = msg;
117                         inode = m->dentry->d_inode;
118                         break;
119                 }        
120                 default:
121                         inode = NULL;
122         }
123
124         return inode;
125 }
126 /* is called also from fsfilt_smfs_get_info */
127 int smfs_get_audit(struct super_block * sb, struct inode * parent,
128                    struct inode * inode,  __u64 * mask)
129 {
130         struct smfs_super_info * smb = S2SMI(sb);
131         struct fsfilt_operations *fsfilt = smb->sm_fsfilt;
132         struct obd_device * obd = smb->smsi_exp->exp_obd;
133         int rc;
134         struct audit_priv * priv = NULL;
135         
136         ENTRY;
137         
138         if (!SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT))
139                 RETURN(-EINVAL);
140         
141         priv = smfs_get_plg_priv(S2SMI(sb), SMFS_PLG_AUDIT);
142               
143         /* omit __iopen__ dir */
144         if (parent->i_ino == SMFS_IOPEN_INO)
145                 RETURN(-ENOENT);
146         
147         if (!priv)
148                 RETURN(-ENOENT);
149         
150         if (IS_AUDIT(priv->a_mask)) {
151                 /* no audit for directories on OSS */
152                 if (inode && S_ISDIR(inode->i_mode) &&
153                     !strcmp(obd->obd_type->typ_name, OBD_FILTER_DEVICENAME))
154                         RETURN(-EINVAL);
155                 (*mask) = priv->a_mask;
156                 RETURN(0);
157         }
158         /* get inode audit EA */
159         rc = fsfilt->fs_get_xattr(parent, AUDIT_ATTR_EA,
160                                   mask, sizeof(*mask));
161         if (rc <= 0)
162                 RETURN(-ENODATA);
163         
164         /* check if parent has audit */
165         if (IS_AUDIT(*mask))
166                 RETURN(0);
167         
168         if (!inode)
169                 RETURN(-ENOENT);
170         
171         rc = fsfilt->fs_get_xattr(inode, AUDIT_ATTR_EA,
172                                   mask, sizeof(*mask));
173         if (rc <= 0)
174                 RETURN(-ENODATA);
175         
176         if (IS_AUDIT(*mask))
177                 RETURN(0);
178
179         RETURN(-ENODATA);
180 }
181
182 int smfs_audit_check(struct inode * parent, hook_op hook, int ret,
183                      struct audit_priv * priv, void * msg)
184 {
185         audit_op code;
186         __u64 mask = 0;
187         int rc = 0;
188         
189         ENTRY;
190
191         if (hook == HOOK_SPECIAL) { 
192                 struct audit_info * info = msg;
193                 code = info->m.code;
194         }
195         else
196                 code = hook2audit(hook);
197
198         rc = smfs_get_audit(parent->i_sb, parent,
199                             get_inode_from_hook(hook, msg),
200                             &mask);
201         if (rc < 0)
202                 RETURN(0);
203         //should only failures be audited?
204         if (ret >= 0 && IS_AUDIT_OP(mask, AUDIT_FAIL))
205                 RETURN(0); 
206
207         //check audit mask
208         RETURN(IS_AUDIT_OP(mask, code));
209 }
210
211 static int smfs_set_fs_audit (struct super_block * sb, __u64 *mask)
212 {
213         struct smfs_super_info * smb = S2SMI(sb);
214         struct fsfilt_operations * fsfilt = smb->sm_fsfilt;
215         int rc = 0;
216         loff_t off = 0;
217         struct file * f = NULL;
218         struct audit_priv *priv;
219         struct lvfs_run_ctxt * ctxt, saved;
220         ENTRY;
221         
222         ctxt = &smb->smsi_exp->exp_obd->obd_lvfs_ctxt;
223         
224         priv = smfs_get_plg_priv(smb, SMFS_PLG_AUDIT);
225         if(!priv) {
226                 CERROR("Audit is not initialized, use mountoptions 'audit'\n");
227                 RETURN(-EINVAL);
228         }
229         
230         push_ctxt(&saved, ctxt, NULL);
231
232         f = filp_open(AUDIT_ATTR_FILE, O_RDWR|O_CREAT, 0600);
233         if (IS_ERR(f)) {
234                 CERROR("cannot get audit_setting file\n");
235                 rc = -EINVAL;
236                 goto exit;
237         }
238                 
239         rc = fsfilt->fs_write_record(f, mask, sizeof(*mask), &off, 1);
240         if (rc) {
241                 CERROR("error writting audit setting: rc = %d\n", rc);
242                 goto exit;
243         }
244         
245         priv->a_mask = (*mask);
246         
247 exit:
248         if (f)
249                 filp_close(f, 0);
250
251         pop_ctxt(&saved, ctxt, NULL);
252
253         RETURN (rc);
254 }
255
256 //set audit attributes for directory/file
257 int smfs_set_audit(struct super_block * sb, struct inode * inode,
258                    __u64 * mask)
259 {
260         void * handle = NULL;
261         struct fsfilt_operations * fsfilt = S2SMI(sb)->sm_fsfilt;
262         int rc = 0;
263         
264         ENTRY;
265         
266         if (IS_AUDIT_OP((*mask), AUDIT_FS))
267                 return smfs_set_fs_audit(sb, mask);
268
269         LASSERT(inode);
270         
271         handle = fsfilt->fs_start(inode, FSFILT_OP_SETATTR, NULL, 0);
272         if (IS_ERR(handle))
273                 RETURN(PTR_ERR(handle));
274         
275         if (fsfilt->fs_set_xattr)
276                 rc = fsfilt->fs_set_xattr(inode, handle, AUDIT_ATTR_EA,
277                                           mask, sizeof(*mask));
278
279         fsfilt->fs_commit(inode->i_sb, inode, handle, 1);
280         RETURN(rc);
281                                 
282 }
283
284 static int smfs_audit_post_op(hook_op code, struct inode * inode, void * msg,
285                               int ret, void * arg)
286 {
287         int rc = 0, len;
288         char * buffer = NULL;
289         struct audit_record * rec = NULL;
290         struct llog_rec_hdr * llh;
291         struct timeval cur_time;
292         struct audit_priv * priv = arg;
293         audit_get_op * handler = priv->audit_get_record;
294
295         //check that we are in lustre ctxt
296         if (!SMFS_IS(I2SMI(inode)->smi_flags, SMFS_PLG_AUDIT))
297                 return 0;
298         
299         if (!handler || !handler[code])
300                 return 0;
301         
302         if (smfs_audit_check(inode, code, ret, priv, msg) == 0)
303                 return 0;
304
305         ENTRY;
306         
307         do_gettimeofday(&cur_time);
308
309         OBD_ALLOC(buffer, PAGE_SIZE);
310         if (!buffer)
311                 RETURN(-ENOMEM);
312         
313         llh = (void*)buffer;
314         //fill common fields
315         rec = (void*)(buffer + sizeof(*llh));
316                
317         rec->result = ret;
318         rec->uid = current->uid;
319         rec->gid = current->gid;
320         rec->nid = current->user->nid;
321         rec->time = cur_time.tv_sec * USEC_PER_SEC + cur_time.tv_usec;
322         
323         len = handler[code](inode, msg, priv, (char*)rec,
324                                            &llh->lrh_type);
325         
326         LASSERT(llh->lrh_type == SMFS_AUDIT_GEN_REC ||
327                 llh->lrh_type == SMFS_AUDIT_NAME_REC);
328
329         llh->lrh_len = size_round(len);
330
331         rc = llog_cat_add_rec(priv->audit_ctxt->loc_handle, llh, NULL,
332                               (void*)rec, NULL, NULL); 
333         if (rc != 0) {
334                 CERROR("Error adding audit record: %d\n", rc);
335                 rc= -EINVAL;
336         } else {
337                 audit_notify(priv->audit_ctxt->loc_handle, priv->au_id2name);
338         }
339         
340         OBD_FREE(buffer, PAGE_SIZE);
341         
342         RETURN(rc);
343 }
344
345 /* Helpers */
346 static int smfs_trans_audit (struct super_block *sb, void *arg,
347                            struct audit_priv * priv)
348 {
349         int size = 1; //one record in log per operation.
350
351         return size;
352 }
353
354 extern int mds_alloc_inode_ids(struct obd_device *, struct inode *,
355                         void *, struct lustre_id *, struct lustre_id *);
356
357 static int smfs_start_audit(struct super_block *sb, void *arg,
358                           struct audit_priv * audit_p)
359 {
360         struct smfs_super_info * smb = S2SMI(sb);
361         struct fsfilt_operations * fsfilt = smb->sm_fsfilt;
362         struct obd_device *obd = arg;
363         struct file * f;
364         int rc = 0;
365
366         ENTRY;
367
368         //is plugin already activated
369         if (SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT))
370                 RETURN(0);
371         
372         rc = audit_start_transferd();
373         if (rc) {
374                 CERROR("can't start audit transfer daemon. rc:%d\n", rc);
375                 RETURN(rc);
376         }
377         
378         if (obd && obd->obd_type && obd->obd_type->typ_name) {
379                 if (!strcmp(obd->obd_type->typ_name, "mds")) {
380                         CDEBUG(D_INODE, "Setup MDS audit handler\n");
381                         audit_mds_setup(obd, sb, audit_p);
382                 }
383                 else if (!strcmp(obd->obd_type->typ_name, "obdfilter")) {
384                         CDEBUG(D_INODE, "Setup OST audit handler\n");
385                         audit_ost_setup(obd, sb, audit_p);
386                 }
387                 else {
388                         CDEBUG(D_INODE, "Unknown obd type %s\n",
389                                obd->obd_type->typ_name);       
390                         RETURN(0);
391                 }
392         }
393         //read fs audit settings if any
394         audit_p->a_mask = AUDIT_OFF;
395
396         f = filp_open(AUDIT_ATTR_FILE, O_RDONLY, 0644);
397         if (!IS_ERR(f)) {
398                 loff_t off = 0;
399                 rc = fsfilt->fs_read_record(f, &audit_p->a_mask, 
400                                         sizeof(audit_p->a_mask), &off);
401                 if (rc) {
402                         CERROR("error reading audit setting: rc = %d\n", rc);
403                 }
404                 filp_close(f, 0);
405         }
406         
407         SMFS_SET(smb->plg_flags, SMFS_PLG_AUDIT);
408
409         RETURN(0);
410 }
411
412 int smfs_stop_audit(struct super_block *sb, void *arg,
413                   struct audit_priv * audit_p)
414 {
415         struct smfs_super_info * smb = S2SMI(sb);
416         struct llog_ctxt *ctxt = audit_p->audit_ctxt;
417         ENTRY;
418
419         if (!SMFS_IS(smb->plg_flags, SMFS_PLG_AUDIT))
420                 RETURN(0);
421
422         audit_stop_transferd();
423
424         SMFS_CLEAR(smb->plg_flags, SMFS_PLG_AUDIT);
425
426         if (ctxt->loc_llogs)
427                 ctxt->loc_llogs->llog_ctxt[LLOG_AUDIT_ORIG_CTXT] = NULL;
428
429         llog_catalog_cleanup(ctxt);
430         OBD_FREE(ctxt, sizeof(*ctxt));
431         audit_p->audit_ctxt = NULL;
432         
433         RETURN(0);
434 }
435
436 int smfs_audit_set_info(struct super_block *sb, void *arg,
437                         struct audit_priv *priv) {
438         struct plg_info_msg * msg = arg;
439         if (KEY_IS(msg->key, "id2name")) {
440                 priv->au_id2name = msg->val;
441         }
442                          
443         return 0;
444 }
445
446 typedef int (*audit_helper)(struct super_block * sb, void *msg, struct audit_priv *);
447 static audit_helper smfs_audit_helpers[PLG_HELPER_MAX] = {
448         [PLG_START]      smfs_start_audit,
449         [PLG_STOP]       smfs_stop_audit,
450         [PLG_TRANS_SIZE] smfs_trans_audit,
451         [PLG_TEST_INODE] NULL,
452         [PLG_SET_INODE]  NULL,
453         [PLG_SET_INFO]   smfs_audit_set_info,
454 };
455
456 static int smfs_audit_help_op(int code, struct super_block * sb,
457                             void * arg, void * priv)
458 {
459         int rc = 0;
460         
461         if (smfs_audit_helpers[code])
462                 rc = smfs_audit_helpers[code](sb, arg, (struct audit_priv *) priv);
463         return rc;
464 }
465
466 static int smfs_exit_audit(struct super_block *sb, 
467                            void * arg)
468 {
469         struct audit_priv * priv = arg;
470         struct smfs_plugin * plg;
471         ENTRY;
472
473         plg = smfs_deregister_plugin(sb, SMFS_PLG_AUDIT);
474         if (plg)
475                 OBD_FREE(plg, sizeof(*plg));
476         else
477                 CERROR("Cannot find AUDIT plugin while unregistering\n");
478         
479         if (priv)
480                 OBD_FREE(priv, sizeof(*priv));
481         
482         RETURN(0);
483 }
484
485 int smfs_init_audit(struct super_block *sb)
486 {
487         int rc = 0;
488         struct audit_priv * priv = NULL;
489         struct smfs_plugin * plg = NULL;
490
491         ENTRY;
492         
493         OBD_ALLOC(plg, sizeof(*plg));
494         if (!plg) {
495                 rc = -ENOMEM;
496                 goto exit;
497         }
498         
499         plg->plg_type = SMFS_PLG_AUDIT;
500         plg->plg_post_op = &smfs_audit_post_op;
501         plg->plg_helper = &smfs_audit_help_op;
502         plg->plg_exit = &smfs_exit_audit;
503
504         OBD_ALLOC(priv, sizeof(*priv));
505         if (!priv) {
506                 rc = -ENOMEM;
507                 goto exit;
508         }
509
510         plg->plg_private = priv;
511         rc = smfs_register_plugin(sb, plg);
512         if (!rc)
513                 RETURN(0);
514 exit:
515         if (priv)
516                 OBD_FREE(priv, sizeof(*priv));
517         
518         if (plg)
519                 OBD_FREE(plg, sizeof(*plg));
520
521         RETURN(rc);
522
523 }
524
525 int audit_client_log(struct super_block * sb, struct audit_msg * msg)
526 {
527         struct smfs_super_info * smb = S2SMI(sb);
528         char *buffer = NULL, *pbuf = NULL;
529         struct audit_record * rec = NULL;
530         struct llog_rec_hdr * llh;
531         struct llog_handle * ll_handle = NULL;
532         int len = 0, rc = 0;
533         struct timeval cur_time;
534         //char name[32];
535         struct audit_priv * priv;
536         
537         ENTRY;
538         
539         do_gettimeofday(&cur_time);
540         
541         priv = smfs_get_plg_priv(smb, SMFS_PLG_AUDIT);
542         if (!priv)
543                 RETURN(-EINVAL);
544         
545         ll_handle = priv->audit_ctxt->loc_handle;
546         
547         OBD_ALLOC(buffer, PAGE_SIZE);
548         if (!buffer)
549                 RETURN(-ENOMEM);
550         
551         llh = (void*)buffer;
552         llh->lrh_type = SMFS_AUDIT_GEN_REC;
553         pbuf = buffer + sizeof(*llh);
554
555         //fill common fields
556         rec = (void*)(pbuf);
557         rec->opcode = msg->code;
558         rec->result = msg->result;
559         rec->uid = msg->uid;
560         rec->gid = msg->gid;
561         rec->nid = msg->nid;
562         rec->time = cur_time.tv_sec * USEC_PER_SEC + cur_time.tv_usec;
563         pbuf += sizeof(*rec);
564         
565         switch (msg->code) {
566                 case AUDIT_READ:    
567                 case AUDIT_WRITE:
568                 case AUDIT_MMAP:
569                 case AUDIT_OPEN:
570                 case AUDIT_STAT:
571                         len = audit_rec_from_id(&pbuf, &msg->id);
572                         break;
573                 default:
574                         CERROR("Unknown code %i in audit_msg\n", msg->code);
575         }
576         
577         llh->lrh_len = size_round(len);
578
579         rc = llog_cat_add_rec(ll_handle, llh, NULL, (void*)rec, NULL, NULL);
580         if (rc != 0) {
581                 CERROR("Error adding audit client record: %d\n", rc);
582                 rc= -EINVAL;
583         } else {
584                 audit_notify(ll_handle, priv->au_id2name);
585         }
586         
587         OBD_FREE(buffer, PAGE_SIZE);
588         return rc;
589 }
590