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