Whamcloud - gitweb
current branches now use lnet from HEAD
[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->opcode = AUDIT_SETATTR;
182         len += audit_fill_id_rec(&pbuf, inode);
183         *type = SMFS_AUDIT_GEN_REC;
184                 
185         return len;
186 }
187
188 int static audit_mds_readlink_rec(struct inode * inode, void * arg, 
189                                   struct audit_priv * priv, char * buffer,
190                                   __u32 *type)
191 {
192         //struct hook_symlink_msg * msg = arg;
193         struct audit_record * rec = (void*)buffer;
194         char * pbuf = buffer + sizeof(*rec);
195         int len = sizeof(*rec);
196         
197         rec->opcode = AUDIT_READLINK;
198         len += audit_fill_id_rec(&pbuf, inode);
199         *type = SMFS_AUDIT_GEN_REC;
200                 
201         return len;
202 }
203
204 int static audit_mds_readdir_rec(struct inode * inode, void * arg, 
205                                  struct audit_priv * priv, char * buffer,
206                                  __u32 *type)
207 {
208         struct audit_record * rec = (void*)buffer;
209         char * pbuf = buffer + sizeof(*rec);
210         int len = sizeof(*rec);
211         
212         rec->opcode = AUDIT_READDIR;
213         len += audit_fill_id_rec(&pbuf, inode);
214         *type = SMFS_AUDIT_GEN_REC;
215                 
216         return len;
217 }
218
219 /* for special records from failed auth and open/stat*/
220 int audit_mds_special_rec(struct inode * inode, void * arg,
221                           struct audit_priv * priv, char *buffer,
222                           __u32 * type)
223 {
224         struct audit_info * info = arg;
225         struct audit_msg * msg = &info->m;
226         struct audit_record * rec = (void*)buffer;
227         char * pbuf = buffer + sizeof(*rec);
228         int len = sizeof(*rec);
229                 
230         //rewrite some fields
231         rec->opcode = msg->code;
232         rec->result = msg->result;
233         rec->uid = msg->uid;
234         rec->gid = msg->gid;
235         rec->nid = msg->nid;
236         
237         /* check id is valid */
238         LASSERT(id_ino(&msg->id));
239         LASSERT(id_fid(&msg->id));
240         // LASSERT(id_type(&msg->id) & S_IFMT);
241         
242         len += audit_rec_from_id(&pbuf, &msg->id);
243         switch (rec->opcode)
244         {
245                 case AUDIT_OPEN:
246                 case AUDIT_CREATE:
247                 case AUDIT_STAT:
248                         if (info->name && info->namelen > 0) { 
249                                 len += audit_fill_name_rec(&pbuf,
250                                                            info->name,
251                                                            info->namelen);
252                                 *type = SMFS_AUDIT_NAME_REC;
253                                 break;
254                         }
255                 default:
256                         *type = SMFS_AUDIT_GEN_REC;
257         }
258         
259         return len;
260 }
261
262 static audit_get_op audit_mds_record[HOOK_MAX] = {
263         [HOOK_CREATE]     audit_mds_create_rec,
264         [HOOK_LINK]       audit_mds_link_rec,
265         [HOOK_UNLINK]     audit_mds_unlink_rec,
266         [HOOK_SYMLINK]    audit_mds_create_rec,
267         [HOOK_READLINK]   audit_mds_readlink_rec,
268         [HOOK_MKDIR]      audit_mds_create_rec,
269         [HOOK_RMDIR]      audit_mds_unlink_rec,
270         [HOOK_MKNOD]      audit_mds_create_rec,
271         [HOOK_RENAME]     audit_mds_rename_rec,
272         [HOOK_SETATTR]    audit_mds_setattr_rec,
273         [HOOK_F_SETATTR]  audit_mds_setattr_rec,
274         [HOOK_SPECIAL]    audit_mds_special_rec,
275         [HOOK_READDIR]    audit_mds_readdir_rec,
276 };
277
278 int audit_mds_setup(struct obd_device * obd, struct super_block *sb,
279                     struct audit_priv *priv) 
280 {
281         int rc;
282         struct smfs_super_info * smb = S2SMI(sb);
283         struct llog_ctxt **ctxt = &priv->audit_ctxt;
284         
285         //this will do OBD_ALLOC() for ctxt
286         rc = llog_catalog_setup(ctxt, AUDIT_MDS_NAME, smb->smsi_exp,
287                                 smb->smsi_ctxt, smb->sm_fsfilt,
288                                 smb->smsi_logs_dir, smb->smsi_objects_dir);
289
290         /* export audit llog ctxt */
291         if (*ctxt) {
292                 (*ctxt)->loc_idx = LLOG_AUDIT_ORIG_CTXT;
293                 (*ctxt)->loc_obd = obd;
294                 (*ctxt)->loc_llogs = &obd->obd_llogs;
295                 (*ctxt)->loc_llogs->llog_ctxt[LLOG_AUDIT_ORIG_CTXT] = *ctxt;
296         }
297         priv->audit_get_record = &audit_mds_record;
298         return 0;
299 }