Whamcloud - gitweb
b=8654
[fs/lustre-release.git] / lustre / smfs / audit_mds.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.h>
36 #include <linux/lustre_lib.h>
37 #include <linux/lustre_log.h>
38 #include <linux/lustre_fsfilt.h>
39 #include <linux/lustre_smfs.h>
40 #include <linux/lustre_audit.h>
41 #include "smfs_internal.h"
42
43 static inline int audit_fill_id_rec (char **pbuf, struct inode * inode)
44 {
45         struct fsfilt_operations *fsfilt = I2FOPS(inode);
46         struct audit_id_record * rec = (void*)(*pbuf);
47         int len = sizeof(*rec);
48         struct lustre_fid fid;
49         int rc = 0;
50         
51         rec->au_num = inode->i_ino;
52         rec->au_type = (S_IFMT & inode->i_mode);
53         rec->au_gen = inode->i_generation;
54         
55         //fid & mdsnum
56         rc = fsfilt->fs_get_md(I2CI(inode), &fid, sizeof(fid), EA_SID);
57         if (rc > 0) {
58                 rec->au_fid = fid.lf_id;
59                 rec->au_mds = fid.lf_group;
60         } else {
61                 //try to add group at least
62                 rec->au_mds = S2SMI(inode->i_sb)->smsi_exp->exp_obd->u.mds.mds_num;
63         }
64         
65         *pbuf += len;
66         return len;
67 }
68
69 int static audit_mds_create_rec(struct inode * parent, void * arg,
70                                 struct audit_priv * priv, char * buffer,
71                                 __u32 * type)
72 {
73         struct hook_msg * msg = arg;
74         struct audit_record * rec = (void*)buffer;
75         char * pbuf = buffer + sizeof(*rec); 
76         struct inode * inode = msg->dentry->d_inode;
77         int len = sizeof(*rec);
78
79         rec->opcode = AUDIT_CREATE;
80         if (priv->result == 0) { //successfull operation
81                 len += audit_fill_id_rec(&pbuf, inode);
82                 *type = SMFS_AUDIT_GEN_REC;
83         }
84         else { //failed operation
85                 len += audit_fill_id_rec(&pbuf, parent);
86                 len += audit_fill_name_rec(&pbuf, msg->dentry->d_name.name,
87                                            msg->dentry->d_name.len);
88                 
89                 *type = SMFS_AUDIT_NAME_REC;
90         }
91         return len;
92 }
93
94 int static audit_mds_link_rec(struct inode * parent, void * arg, 
95                               struct audit_priv * priv, char * buffer,
96                               __u32 *type)
97 {
98         struct hook_link_msg * msg = arg;
99         struct audit_record * rec = (void*)buffer;
100         char * pbuf = buffer + sizeof(*rec);
101         struct inode * inode = msg->dentry->d_inode;
102         int len = sizeof(*rec);
103
104         rec->opcode = AUDIT_LINK;
105         
106         /* these things will be needed always */
107         len += audit_fill_id_rec(&pbuf, inode);
108         len += audit_fill_id_rec(&pbuf, parent);
109         len += audit_fill_name_rec(&pbuf, msg->dentry->d_name.name,
110                                    msg->dentry->d_name.len);
111         *type = SMFS_AUDIT_NAME_REC;
112         
113         return len;
114 }
115
116 int static audit_mds_unlink_rec(struct inode * parent, void * arg,
117                                 struct audit_priv * priv, char * buffer,
118                                 __u32 *type)
119 {
120         struct hook_unlink_msg * msg = arg;
121         struct inode * inode = msg->dentry->d_inode;
122         struct audit_record * rec = (void*)buffer;
123         char * pbuf = buffer + sizeof(*rec);
124         int len = sizeof(*rec);
125               
126         rec->opcode = AUDIT_UNLINK;
127         
128         
129         len += audit_fill_id_rec(&pbuf, inode);
130         len += audit_fill_id_rec(&pbuf, parent);
131         if (priv->result == 0) {
132                 len += audit_fill_name_rec(&pbuf, msg->dentry->d_name.name,
133                                    msg->dentry->d_name.len);
134                 *type = SMFS_AUDIT_NAME_REC;
135         } else {
136                 //in case of failure name shouldn't be saved
137                 *type = SMFS_AUDIT_GEN_REC;
138         }
139         
140         return len;
141 }
142
143 int static audit_mds_rename_rec(struct inode * parent, void * arg, 
144                                 struct audit_priv * priv, char * buffer,
145                                 __u32 *type)
146 {
147         struct hook_rename_msg * msg = arg;
148         struct inode * inode = msg->dentry->d_inode;
149         struct audit_record * rec = (void*)buffer;
150         char * pbuf = buffer + sizeof(*rec);
151         int len = sizeof(*rec);
152         
153         rec->opcode = AUDIT_RENAME;
154         
155         len += audit_fill_id_rec(&pbuf, inode);
156         if (priv->result == 0) {
157                 len += audit_fill_id_rec(&pbuf, msg->old_dir);
158                 len += audit_fill_name_rec(&pbuf, msg->dentry->d_name.name,
159                                            msg->dentry->d_name.len);
160         } else { 
161                 len += audit_fill_id_rec(&pbuf, msg->new_dir);
162                 len += audit_fill_name_rec(&pbuf, msg->new_dentry->d_name.name,
163                                            msg->new_dentry->d_name.len);
164         }
165         
166         *type = SMFS_AUDIT_NAME_REC;
167                 
168         return len;
169
170 }
171
172 int static audit_mds_setattr_rec(struct inode * inode, void * arg, 
173                               struct audit_priv * priv, char * buffer,
174                               __u32 *type)
175 {
176         struct hook_attr_msg * msg = arg;
177         struct audit_record * rec = (void*)buffer;
178         char * pbuf = buffer + sizeof(*rec);
179         int len = sizeof(*rec);
180         
181         rec->nid = msg->attr->ia_valid;
182         rec->opcode = AUDIT_SETATTR;
183         len += audit_fill_id_rec(&pbuf, inode);
184         *type = SMFS_AUDIT_GEN_REC;
185                 
186         return len;
187 }
188
189 int static audit_mds_readlink_rec(struct inode * inode, void * arg, 
190                                   struct audit_priv * priv, char * buffer,
191                                   __u32 *type)
192 {
193         //struct hook_symlink_msg * msg = arg;
194         struct audit_record * rec = (void*)buffer;
195         char * pbuf = buffer + sizeof(*rec);
196         int len = sizeof(*rec);
197         
198         rec->opcode = AUDIT_READLINK;
199         len += audit_fill_id_rec(&pbuf, inode);
200         *type = SMFS_AUDIT_GEN_REC;
201                 
202         return len;
203 }
204
205 int static audit_mds_readdir_rec(struct inode * inode, void * arg, 
206                                  struct audit_priv * priv, char * buffer,
207                                  __u32 *type)
208 {
209         struct audit_record * rec = (void*)buffer;
210         char * pbuf = buffer + sizeof(*rec);
211         int len = sizeof(*rec);
212         
213         rec->opcode = AUDIT_READDIR;
214         len += audit_fill_id_rec(&pbuf, inode);
215         *type = SMFS_AUDIT_GEN_REC;
216                 
217         return len;
218 }
219
220 /* for special records from failed auth and open/stat*/
221 int audit_mds_special_rec(struct inode * inode, void * arg,
222                           struct audit_priv * priv, char *buffer,
223                           __u32 * type)
224 {
225         struct audit_info * info = arg;
226         struct audit_msg * msg = &info->m;
227         struct audit_record * rec = (void*)buffer;
228         char * pbuf = buffer + sizeof(*rec);
229         int len = sizeof(*rec);
230                 
231         //rewrite some fields
232         rec->opcode = msg->code;
233         rec->result = msg->result;
234         rec->uid = msg->uid;
235         rec->gid = msg->gid;
236         rec->nid = msg->nid;
237         
238         /* check id is valid */
239         LASSERT(id_ino(&msg->id));
240         LASSERT(id_fid(&msg->id));
241         // LASSERT(id_type(&msg->id) & S_IFMT);
242         
243         len += audit_rec_from_id(&pbuf, &msg->id);
244         switch (rec->opcode)
245         {
246                 case AUDIT_OPEN:
247                 case AUDIT_CREATE:
248                 case AUDIT_STAT:
249                         if (info->name && info->namelen > 0) { 
250                                 len += audit_fill_name_rec(&pbuf,
251                                                            info->name,
252                                                            info->namelen);
253                                 *type = SMFS_AUDIT_NAME_REC;
254                                 break;
255                         }
256                 default:
257                         *type = SMFS_AUDIT_GEN_REC;
258         }
259         
260         return len;
261 }
262
263 static audit_get_op audit_mds_record[HOOK_MAX] = {
264         [HOOK_CREATE]     audit_mds_create_rec,
265         [HOOK_LINK]       audit_mds_link_rec,
266         [HOOK_UNLINK]     audit_mds_unlink_rec,
267         [HOOK_SYMLINK]    audit_mds_create_rec,
268         [HOOK_READLINK]   audit_mds_readlink_rec,
269         [HOOK_MKDIR]      audit_mds_create_rec,
270         [HOOK_RMDIR]      audit_mds_unlink_rec,
271         [HOOK_MKNOD]      audit_mds_create_rec,
272         [HOOK_RENAME]     audit_mds_rename_rec,
273         [HOOK_SETATTR]    audit_mds_setattr_rec,
274         [HOOK_F_SETATTR]  audit_mds_setattr_rec,
275         [HOOK_SPECIAL]    audit_mds_special_rec,
276         [HOOK_READDIR]    audit_mds_readdir_rec,
277 };
278
279 int audit_mds_setup(struct obd_device * obd, struct super_block *sb,
280                     struct audit_priv *priv) 
281 {
282         int rc;
283         struct smfs_super_info * smb = S2SMI(sb);
284         struct llog_ctxt **ctxt = &priv->audit_ctxt;
285         
286         //this will do OBD_ALLOC() for ctxt
287         rc = llog_catalog_setup(ctxt, AUDIT_MDS_NAME, smb->smsi_exp,
288                                 smb->smsi_ctxt, smb->sm_fsfilt,
289                                 smb->smsi_logs_dir, smb->smsi_objects_dir);
290
291         /* export audit llog ctxt */
292         if (*ctxt) {
293                 (*ctxt)->loc_idx = LLOG_AUDIT_ORIG_CTXT;
294                 (*ctxt)->loc_obd = obd;
295                 (*ctxt)->loc_llogs = &obd->obd_llogs;
296                 (*ctxt)->loc_llogs->llog_ctxt[LLOG_AUDIT_ORIG_CTXT] = *ctxt;
297         }
298         priv->audit_get_record = &audit_mds_record;
299         return 0;
300 }