aboutsummaryrefslogtreecommitdiffstats
path: root/security
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@g5.osdl.org>2005-09-13 12:48:54 -0400
committerLinus Torvalds <torvalds@g5.osdl.org>2005-09-13 12:48:54 -0400
commitddbf9ef385bfbef897210733abfb73cb9b94ecec (patch)
tree64a9e965a71eef13e813a3327f8d74aa7168ee19 /security
parent5d54e69c68c05b162a56f9914cae72afd7e6f40a (diff)
parent2c40579bdc2a94977fcff2521d5b53a97c33e77a (diff)
Merge master.kernel.org:/pub/scm/linux/kernel/git/chrisw/lsm-2.6
Diffstat (limited to 'security')
-rw-r--r--security/Kconfig1
-rw-r--r--security/Makefile2
-rw-r--r--security/inode.c347
-rw-r--r--security/seclvl.c228
4 files changed, 419 insertions, 159 deletions
diff --git a/security/Kconfig b/security/Kconfig
index dcf04a09185d..64d3f1e9ca85 100644
--- a/security/Kconfig
+++ b/security/Kconfig
@@ -35,6 +35,7 @@ config KEYS_DEBUG_PROC_KEYS
35 35
36config SECURITY 36config SECURITY
37 bool "Enable different security models" 37 bool "Enable different security models"
38 depends on SYSFS
38 help 39 help
39 This allows you to choose different security modules to be 40 This allows you to choose different security modules to be
40 configured into your kernel. 41 configured into your kernel.
diff --git a/security/Makefile b/security/Makefile
index 197cc2f3f1ec..8cbbf2f36709 100644
--- a/security/Makefile
+++ b/security/Makefile
@@ -11,7 +11,7 @@ obj-y += commoncap.o
11endif 11endif
12 12
13# Object file lists 13# Object file lists
14obj-$(CONFIG_SECURITY) += security.o dummy.o 14obj-$(CONFIG_SECURITY) += security.o dummy.o inode.o
15# Must precede capability.o in order to stack properly. 15# Must precede capability.o in order to stack properly.
16obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o 16obj-$(CONFIG_SECURITY_SELINUX) += selinux/built-in.o
17obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o 17obj-$(CONFIG_SECURITY_CAPABILITIES) += commoncap.o capability.o
diff --git a/security/inode.c b/security/inode.c
new file mode 100644
index 000000000000..a5964502ae30
--- /dev/null
+++ b/security/inode.c
@@ -0,0 +1,347 @@
1/*
2 * inode.c - securityfs
3 *
4 * Copyright (C) 2005 Greg Kroah-Hartman <gregkh@suse.de>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License version
8 * 2 as published by the Free Software Foundation.
9 *
10 * Based on fs/debugfs/inode.c which had the following copyright notice:
11 * Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
12 * Copyright (C) 2004 IBM Inc.
13 */
14
15/* #define DEBUG */
16#include <linux/config.h>
17#include <linux/module.h>
18#include <linux/fs.h>
19#include <linux/mount.h>
20#include <linux/pagemap.h>
21#include <linux/init.h>
22#include <linux/namei.h>
23#include <linux/security.h>
24
25#define SECURITYFS_MAGIC 0x73636673
26
27static struct vfsmount *mount;
28static int mount_count;
29
30/*
31 * TODO:
32 * I think I can get rid of these default_file_ops, but not quite sure...
33 */
34static ssize_t default_read_file(struct file *file, char __user *buf,
35 size_t count, loff_t *ppos)
36{
37 return 0;
38}
39
40static ssize_t default_write_file(struct file *file, const char __user *buf,
41 size_t count, loff_t *ppos)
42{
43 return count;
44}
45
46static int default_open(struct inode *inode, struct file *file)
47{
48 if (inode->u.generic_ip)
49 file->private_data = inode->u.generic_ip;
50
51 return 0;
52}
53
54static struct file_operations default_file_ops = {
55 .read = default_read_file,
56 .write = default_write_file,
57 .open = default_open,
58};
59
60static struct inode *get_inode(struct super_block *sb, int mode, dev_t dev)
61{
62 struct inode *inode = new_inode(sb);
63
64 if (inode) {
65 inode->i_mode = mode;
66 inode->i_uid = 0;
67 inode->i_gid = 0;
68 inode->i_blksize = PAGE_CACHE_SIZE;
69 inode->i_blocks = 0;
70 inode->i_atime = inode->i_mtime = inode->i_ctime = CURRENT_TIME;
71 switch (mode & S_IFMT) {
72 default:
73 init_special_inode(inode, mode, dev);
74 break;
75 case S_IFREG:
76 inode->i_fop = &default_file_ops;
77 break;
78 case S_IFDIR:
79 inode->i_op = &simple_dir_inode_operations;
80 inode->i_fop = &simple_dir_operations;
81
82 /* directory inodes start off with i_nlink == 2 (for "." entry) */
83 inode->i_nlink++;
84 break;
85 }
86 }
87 return inode;
88}
89
90/* SMP-safe */
91static int mknod(struct inode *dir, struct dentry *dentry,
92 int mode, dev_t dev)
93{
94 struct inode *inode;
95 int error = -EPERM;
96
97 if (dentry->d_inode)
98 return -EEXIST;
99
100 inode = get_inode(dir->i_sb, mode, dev);
101 if (inode) {
102 d_instantiate(dentry, inode);
103 dget(dentry);
104 error = 0;
105 }
106 return error;
107}
108
109static int mkdir(struct inode *dir, struct dentry *dentry, int mode)
110{
111 int res;
112
113 mode = (mode & (S_IRWXUGO | S_ISVTX)) | S_IFDIR;
114 res = mknod(dir, dentry, mode, 0);
115 if (!res)
116 dir->i_nlink++;
117 return res;
118}
119
120static int create(struct inode *dir, struct dentry *dentry, int mode)
121{
122 mode = (mode & S_IALLUGO) | S_IFREG;
123 return mknod(dir, dentry, mode, 0);
124}
125
126static inline int positive(struct dentry *dentry)
127{
128 return dentry->d_inode && !d_unhashed(dentry);
129}
130
131static int fill_super(struct super_block *sb, void *data, int silent)
132{
133 static struct tree_descr files[] = {{""}};
134
135 return simple_fill_super(sb, SECURITYFS_MAGIC, files);
136}
137
138static struct super_block *get_sb(struct file_system_type *fs_type,
139 int flags, const char *dev_name,
140 void *data)
141{
142 return get_sb_single(fs_type, flags, data, fill_super);
143}
144
145static struct file_system_type fs_type = {
146 .owner = THIS_MODULE,
147 .name = "securityfs",
148 .get_sb = get_sb,
149 .kill_sb = kill_litter_super,
150};
151
152static int create_by_name(const char *name, mode_t mode,
153 struct dentry *parent,
154 struct dentry **dentry)
155{
156 int error = 0;
157
158 *dentry = NULL;
159
160 /* If the parent is not specified, we create it in the root.
161 * We need the root dentry to do this, which is in the super
162 * block. A pointer to that is in the struct vfsmount that we
163 * have around.
164 */
165 if (!parent ) {
166 if (mount && mount->mnt_sb) {
167 parent = mount->mnt_sb->s_root;
168 }
169 }
170 if (!parent) {
171 pr_debug("securityfs: Ah! can not find a parent!\n");
172 return -EFAULT;
173 }
174
175 down(&parent->d_inode->i_sem);
176 *dentry = lookup_one_len(name, parent, strlen(name));
177 if (!IS_ERR(dentry)) {
178 if ((mode & S_IFMT) == S_IFDIR)
179 error = mkdir(parent->d_inode, *dentry, mode);
180 else
181 error = create(parent->d_inode, *dentry, mode);
182 } else
183 error = PTR_ERR(dentry);
184 up(&parent->d_inode->i_sem);
185
186 return error;
187}
188
189/**
190 * securityfs_create_file - create a file in the securityfs filesystem
191 *
192 * @name: a pointer to a string containing the name of the file to create.
193 * @mode: the permission that the file should have
194 * @parent: a pointer to the parent dentry for this file. This should be a
195 * directory dentry if set. If this paramater is NULL, then the
196 * file will be created in the root of the securityfs filesystem.
197 * @data: a pointer to something that the caller will want to get to later
198 * on. The inode.u.generic_ip pointer will point to this value on
199 * the open() call.
200 * @fops: a pointer to a struct file_operations that should be used for
201 * this file.
202 *
203 * This is the basic "create a file" function for securityfs. It allows for a
204 * wide range of flexibility in createing a file, or a directory (if you
205 * want to create a directory, the securityfs_create_dir() function is
206 * recommended to be used instead.)
207 *
208 * This function will return a pointer to a dentry if it succeeds. This
209 * pointer must be passed to the securityfs_remove() function when the file is
210 * to be removed (no automatic cleanup happens if your module is unloaded,
211 * you are responsible here.) If an error occurs, NULL will be returned.
212 *
213 * If securityfs is not enabled in the kernel, the value -ENODEV will be
214 * returned. It is not wise to check for this value, but rather, check for
215 * NULL or !NULL instead as to eliminate the need for #ifdef in the calling
216 * code.
217 */
218struct dentry *securityfs_create_file(const char *name, mode_t mode,
219 struct dentry *parent, void *data,
220 struct file_operations *fops)
221{
222 struct dentry *dentry = NULL;
223 int error;
224
225 pr_debug("securityfs: creating file '%s'\n",name);
226
227 error = simple_pin_fs("securityfs", &mount, &mount_count);
228 if (error) {
229 dentry = ERR_PTR(error);
230 goto exit;
231 }
232
233 error = create_by_name(name, mode, parent, &dentry);
234 if (error) {
235 dentry = ERR_PTR(error);
236 simple_release_fs(&mount, &mount_count);
237 goto exit;
238 }
239
240 if (dentry->d_inode) {
241 if (fops)
242 dentry->d_inode->i_fop = fops;
243 if (data)
244 dentry->d_inode->u.generic_ip = data;
245 }
246exit:
247 return dentry;
248}
249EXPORT_SYMBOL_GPL(securityfs_create_file);
250
251/**
252 * securityfs_create_dir - create a directory in the securityfs filesystem
253 *
254 * @name: a pointer to a string containing the name of the directory to
255 * create.
256 * @parent: a pointer to the parent dentry for this file. This should be a
257 * directory dentry if set. If this paramater is NULL, then the
258 * directory will be created in the root of the securityfs filesystem.
259 *
260 * This function creates a directory in securityfs with the given name.
261 *
262 * This function will return a pointer to a dentry if it succeeds. This
263 * pointer must be passed to the securityfs_remove() function when the file is
264 * to be removed (no automatic cleanup happens if your module is unloaded,
265 * you are responsible here.) If an error occurs, NULL will be returned.
266 *
267 * If securityfs is not enabled in the kernel, the value -ENODEV will be
268 * returned. It is not wise to check for this value, but rather, check for
269 * NULL or !NULL instead as to eliminate the need for #ifdef in the calling
270 * code.
271 */
272struct dentry *securityfs_create_dir(const char *name, struct dentry *parent)
273{
274 return securityfs_create_file(name,
275 S_IFDIR | S_IRWXU | S_IRUGO | S_IXUGO,
276 parent, NULL, NULL);
277}
278EXPORT_SYMBOL_GPL(securityfs_create_dir);
279
280/**
281 * securityfs_remove - removes a file or directory from the securityfs filesystem
282 *
283 * @dentry: a pointer to a the dentry of the file or directory to be
284 * removed.
285 *
286 * This function removes a file or directory in securityfs that was previously
287 * created with a call to another securityfs function (like
288 * securityfs_create_file() or variants thereof.)
289 *
290 * This function is required to be called in order for the file to be
291 * removed, no automatic cleanup of files will happen when a module is
292 * removed, you are responsible here.
293 */
294void securityfs_remove(struct dentry *dentry)
295{
296 struct dentry *parent;
297
298 if (!dentry)
299 return;
300
301 parent = dentry->d_parent;
302 if (!parent || !parent->d_inode)
303 return;
304
305 down(&parent->d_inode->i_sem);
306 if (positive(dentry)) {
307 if (dentry->d_inode) {
308 if (S_ISDIR(dentry->d_inode->i_mode))
309 simple_rmdir(parent->d_inode, dentry);
310 else
311 simple_unlink(parent->d_inode, dentry);
312 dput(dentry);
313 }
314 }
315 up(&parent->d_inode->i_sem);
316 simple_release_fs(&mount, &mount_count);
317}
318EXPORT_SYMBOL_GPL(securityfs_remove);
319
320static decl_subsys(security, NULL, NULL);
321
322static int __init securityfs_init(void)
323{
324 int retval;
325
326 kset_set_kset_s(&security_subsys, kernel_subsys);
327 retval = subsystem_register(&security_subsys);
328 if (retval)
329 return retval;
330
331 retval = register_filesystem(&fs_type);
332 if (retval)
333 subsystem_unregister(&security_subsys);
334 return retval;
335}
336
337static void __exit securityfs_exit(void)
338{
339 simple_release_fs(&mount, &mount_count);
340 unregister_filesystem(&fs_type);
341 subsystem_unregister(&security_subsys);
342}
343
344core_initcall(securityfs_init);
345module_exit(securityfs_exit);
346MODULE_LICENSE("GPL");
347
diff --git a/security/seclvl.c b/security/seclvl.c
index 96b1f2122f67..dc4e17b6eaf6 100644
--- a/security/seclvl.c
+++ b/security/seclvl.c
@@ -119,69 +119,6 @@ MODULE_PARM_DESC(hideHash, "When set to 0, reading seclvl/passwd from sysfs "
119 } while (0) 119 } while (0)
120 120
121/** 121/**
122 * kobject stuff
123 */
124
125struct subsystem seclvl_subsys;
126
127struct seclvl_obj {
128 char *name;
129 struct list_head slot_list;
130 struct kobject kobj;
131};
132
133/**
134 * There is a seclvl_attribute struct for each file in sysfs.
135 *
136 * In our case, we have one of these structs for "passwd" and another
137 * for "seclvl".
138 */
139struct seclvl_attribute {
140 struct attribute attr;
141 ssize_t(*show) (struct seclvl_obj *, char *);
142 ssize_t(*store) (struct seclvl_obj *, const char *, size_t);
143};
144
145/**
146 * When this function is called, one of the files in sysfs is being
147 * written to. attribute->store is a function pointer to whatever the
148 * struct seclvl_attribute store function pointer points to. It is
149 * unique for "passwd" and "seclvl".
150 */
151static ssize_t
152seclvl_attr_store(struct kobject *kobj,
153 struct attribute *attr, const char *buf, size_t len)
154{
155 struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
156 struct seclvl_attribute *attribute =
157 container_of(attr, struct seclvl_attribute, attr);
158 return attribute->store ? attribute->store(obj, buf, len) : -EIO;
159}
160
161static ssize_t
162seclvl_attr_show(struct kobject *kobj, struct attribute *attr, char *buf)
163{
164 struct seclvl_obj *obj = container_of(kobj, struct seclvl_obj, kobj);
165 struct seclvl_attribute *attribute =
166 container_of(attr, struct seclvl_attribute, attr);
167 return attribute->show ? attribute->show(obj, buf) : -EIO;
168}
169
170/**
171 * Callback function pointers for show and store
172 */
173static struct sysfs_ops seclvlfs_sysfs_ops = {
174 .show = seclvl_attr_show,
175 .store = seclvl_attr_store,
176};
177
178static struct kobj_type seclvl_ktype = {
179 .sysfs_ops = &seclvlfs_sysfs_ops
180};
181
182decl_subsys(seclvl, &seclvl_ktype, NULL);
183
184/**
185 * The actual security level. Ranges between -1 and 2 inclusive. 122 * The actual security level. Ranges between -1 and 2 inclusive.
186 */ 123 */
187static int seclvl; 124static int seclvl;
@@ -213,97 +150,44 @@ static int seclvl_sanity(int reqlvl)
213} 150}
214 151
215/** 152/**
216 * Called whenever the user reads the sysfs handle to this kernel
217 * object
218 */
219static ssize_t seclvl_read_file(struct seclvl_obj *obj, char *buff)
220{
221 return snprintf(buff, PAGE_SIZE, "%d\n", seclvl);
222}
223
224/**
225 * security level advancement rules: 153 * security level advancement rules:
226 * Valid levels are -1 through 2, inclusive. 154 * Valid levels are -1 through 2, inclusive.
227 * From -1, stuck. [ in case compiled into kernel ] 155 * From -1, stuck. [ in case compiled into kernel ]
228 * From 0 or above, can only increment. 156 * From 0 or above, can only increment.
229 */ 157 */
230static int do_seclvl_advance(int newlvl) 158static void do_seclvl_advance(void *data, u64 val)
231{ 159{
232 if (newlvl <= seclvl) { 160 int ret;
233 seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl " 161 int newlvl = (int)val;
234 "[%d]\n", newlvl); 162
235 return -EINVAL; 163 ret = seclvl_sanity(newlvl);
236 } 164 if (ret)
165 return;
166
237 if (newlvl > 2) { 167 if (newlvl > 2) {
238 seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl " 168 seclvl_printk(1, KERN_WARNING, "Cannot advance to seclvl "
239 "[%d]\n", newlvl); 169 "[%d]\n", newlvl);
240 return -EINVAL; 170 return;
241 } 171 }
242 if (seclvl == -1) { 172 if (seclvl == -1) {
243 seclvl_printk(1, KERN_WARNING, "Not allowed to advance to " 173 seclvl_printk(1, KERN_WARNING, "Not allowed to advance to "
244 "seclvl [%d]\n", seclvl); 174 "seclvl [%d]\n", seclvl);
245 return -EPERM; 175 return;
246 } 176 }
247 seclvl = newlvl; 177 seclvl = newlvl; /* would it be more "correct" to set *data? */
248 return 0; 178 return;
249} 179}
250 180
251/** 181static u64 seclvl_int_get(void *data)
252 * Called whenever the user writes to the sysfs handle to this kernel
253 * object (seclvl/seclvl). It expects a single-digit number.
254 */
255static ssize_t
256seclvl_write_file(struct seclvl_obj *obj, const char *buff, size_t count)
257{ 182{
258 unsigned long val; 183 return *(int *)data;
259 if (count > 2 || (count == 2 && buff[1] != '\n')) {
260 seclvl_printk(1, KERN_WARNING, "Invalid value passed to "
261 "seclvl: [%s]\n", buff);
262 return -EINVAL;
263 }
264 val = buff[0] - 48;
265 if (seclvl_sanity(val)) {
266 seclvl_printk(1, KERN_WARNING, "Illegal secure level "
267 "requested: [%d]\n", (int)val);
268 return -EPERM;
269 }
270 if (do_seclvl_advance(val)) {
271 seclvl_printk(0, KERN_ERR, "Failure advancing security level "
272 "to %lu\n", val);
273 }
274 return count;
275} 184}
276 185
277/* Generate sysfs_attr_seclvl */ 186DEFINE_SIMPLE_ATTRIBUTE(seclvl_file_ops, seclvl_int_get, do_seclvl_advance, "%lld\n");
278static struct seclvl_attribute sysfs_attr_seclvl =
279__ATTR(seclvl, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_file,
280 seclvl_write_file);
281 187
282static unsigned char hashedPassword[SHA1_DIGEST_SIZE]; 188static unsigned char hashedPassword[SHA1_DIGEST_SIZE];
283 189
284/** 190/**
285 * Called whenever the user reads the sysfs passwd handle.
286 */
287static ssize_t seclvl_read_passwd(struct seclvl_obj *obj, char *buff)
288{
289 /* So just how good *is* your password? :-) */
290 char tmp[3];
291 int i = 0;
292 buff[0] = '\0';
293 if (hideHash) {
294 /* Security through obscurity */
295 return 0;
296 }
297 while (i < SHA1_DIGEST_SIZE) {
298 snprintf(tmp, 3, "%02x", hashedPassword[i]);
299 strncat(buff, tmp, 2);
300 i++;
301 }
302 strcat(buff, "\n");
303 return ((SHA1_DIGEST_SIZE * 2) + 1);
304}
305
306/**
307 * Converts a block of plaintext of into its SHA1 hashed value. 191 * Converts a block of plaintext of into its SHA1 hashed value.
308 * 192 *
309 * It would be nice if crypto had a wrapper to do this for us linear 193 * It would be nice if crypto had a wrapper to do this for us linear
@@ -347,12 +231,15 @@ plaintext_to_sha1(unsigned char *hash, const char *plaintext, int len)
347 * object. It hashes the password and compares the hashed results. 231 * object. It hashes the password and compares the hashed results.
348 */ 232 */
349static ssize_t 233static ssize_t
350seclvl_write_passwd(struct seclvl_obj *obj, const char *buff, size_t count) 234passwd_write_file(struct file * file, const char __user * buf,
235 size_t count, loff_t *ppos)
351{ 236{
352 int i; 237 int i;
353 unsigned char tmp[SHA1_DIGEST_SIZE]; 238 unsigned char tmp[SHA1_DIGEST_SIZE];
239 char *page;
354 int rc; 240 int rc;
355 int len; 241 int len;
242
356 if (!*passwd && !*sha1_passwd) { 243 if (!*passwd && !*sha1_passwd) {
357 seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the " 244 seclvl_printk(0, KERN_ERR, "Attempt to password-unlock the "
358 "seclvl module, but neither a plain text " 245 "seclvl module, but neither a plain text "
@@ -363,13 +250,26 @@ seclvl_write_passwd(struct seclvl_obj *obj, const char *buff, size_t count)
363 "maintainer about this event.\n"); 250 "maintainer about this event.\n");
364 return -EINVAL; 251 return -EINVAL;
365 } 252 }
366 len = strlen(buff); 253
254 if (count < 0 || count >= PAGE_SIZE)
255 return -ENOMEM;
256 if (*ppos != 0) {
257 return -EINVAL;
258 }
259 page = (char *)get_zeroed_page(GFP_KERNEL);
260 if (!page)
261 return -ENOMEM;
262 len = -EFAULT;
263 if (copy_from_user(page, buf, count))
264 goto out;
265
266 len = strlen(page);
367 /* ``echo "secret" > seclvl/passwd'' includes a newline */ 267 /* ``echo "secret" > seclvl/passwd'' includes a newline */
368 if (buff[len - 1] == '\n') { 268 if (page[len - 1] == '\n') {
369 len--; 269 len--;
370 } 270 }
371 /* Hash the password, then compare the hashed values */ 271 /* Hash the password, then compare the hashed values */
372 if ((rc = plaintext_to_sha1(tmp, buff, len))) { 272 if ((rc = plaintext_to_sha1(tmp, page, len))) {
373 seclvl_printk(0, KERN_ERR, "Error hashing password: rc = " 273 seclvl_printk(0, KERN_ERR, "Error hashing password: rc = "
374 "[%d]\n", rc); 274 "[%d]\n", rc);
375 return rc; 275 return rc;
@@ -382,13 +282,16 @@ seclvl_write_passwd(struct seclvl_obj *obj, const char *buff, size_t count)
382 seclvl_printk(0, KERN_INFO, 282 seclvl_printk(0, KERN_INFO,
383 "Password accepted; seclvl reduced to 0.\n"); 283 "Password accepted; seclvl reduced to 0.\n");
384 seclvl = 0; 284 seclvl = 0;
385 return count; 285 len = count;
286
287out:
288 free_page((unsigned long)page);
289 return len;
386} 290}
387 291
388/* Generate sysfs_attr_passwd */ 292static struct file_operations passwd_file_ops = {
389static struct seclvl_attribute sysfs_attr_passwd = 293 .write = passwd_write_file,
390__ATTR(passwd, (S_IFREG | S_IRUGO | S_IWUSR), seclvl_read_passwd, 294};
391 seclvl_write_passwd);
392 295
393/** 296/**
394 * Explicitely disallow ptrace'ing the init process. 297 * Explicitely disallow ptrace'ing the init process.
@@ -647,22 +550,34 @@ static int processPassword(void)
647} 550}
648 551
649/** 552/**
650 * Sysfs registrations 553 * securityfs registrations
651 */ 554 */
652static int doSysfsRegistrations(void) 555struct dentry *dir_ino, *seclvl_ino, *passwd_ino;
556
557static int seclvlfs_register(void)
653{ 558{
654 int rc = 0; 559 dir_ino = securityfs_create_dir("seclvl", NULL);
655 if ((rc = subsystem_register(&seclvl_subsys))) { 560 if (!dir_ino)
656 seclvl_printk(0, KERN_WARNING, 561 return -EFAULT;
657 "Error [%d] registering seclvl subsystem\n", rc); 562
658 return rc; 563 seclvl_ino = securityfs_create_file("seclvl", S_IRUGO | S_IWUSR,
659 } 564 dir_ino, &seclvl, &seclvl_file_ops);
660 sysfs_create_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr); 565 if (!seclvl_ino)
566 goto out_deldir;
661 if (*passwd || *sha1_passwd) { 567 if (*passwd || *sha1_passwd) {
662 sysfs_create_file(&seclvl_subsys.kset.kobj, 568 passwd_ino = securityfs_create_file("passwd", S_IRUGO | S_IWUSR,
663 &sysfs_attr_passwd.attr); 569 dir_ino, NULL, &passwd_file_ops);
570 if (!passwd_ino)
571 goto out_delf;
664 } 572 }
665 return 0; 573 return 0;
574
575out_deldir:
576 securityfs_remove(dir_ino);
577out_delf:
578 securityfs_remove(seclvl_ino);
579
580 return -EFAULT;
666} 581}
667 582
668/** 583/**
@@ -677,8 +592,6 @@ static int __init seclvl_init(void)
677 rc = -EINVAL; 592 rc = -EINVAL;
678 goto exit; 593 goto exit;
679 } 594 }
680 sysfs_attr_seclvl.attr.owner = THIS_MODULE;
681 sysfs_attr_passwd.attr.owner = THIS_MODULE;
682 if (initlvl < -1 || initlvl > 2) { 595 if (initlvl < -1 || initlvl > 2) {
683 seclvl_printk(0, KERN_ERR, "Error: bad initial securelevel " 596 seclvl_printk(0, KERN_ERR, "Error: bad initial securelevel "
684 "[%d].\n", initlvl); 597 "[%d].\n", initlvl);
@@ -706,7 +619,7 @@ static int __init seclvl_init(void)
706 } /* if primary module registered */ 619 } /* if primary module registered */
707 secondary = 1; 620 secondary = 1;
708 } /* if we registered ourselves with the security framework */ 621 } /* if we registered ourselves with the security framework */
709 if ((rc = doSysfsRegistrations())) { 622 if ((rc = seclvlfs_register())) {
710 seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n"); 623 seclvl_printk(0, KERN_ERR, "Error registering with sysfs\n");
711 goto exit; 624 goto exit;
712 } 625 }
@@ -724,12 +637,11 @@ static int __init seclvl_init(void)
724 */ 637 */
725static void __exit seclvl_exit(void) 638static void __exit seclvl_exit(void)
726{ 639{
727 sysfs_remove_file(&seclvl_subsys.kset.kobj, &sysfs_attr_seclvl.attr); 640 securityfs_remove(seclvl_ino);
728 if (*passwd || *sha1_passwd) { 641 if (*passwd || *sha1_passwd) {
729 sysfs_remove_file(&seclvl_subsys.kset.kobj, 642 securityfs_remove(passwd_ino);
730 &sysfs_attr_passwd.attr);
731 } 643 }
732 subsystem_unregister(&seclvl_subsys); 644 securityfs_remove(dir_ino);
733 if (secondary == 1) { 645 if (secondary == 1) {
734 mod_unreg_security(MY_NAME, &seclvl_ops); 646 mod_unreg_security(MY_NAME, &seclvl_ops);
735 } else if (unregister_security(&seclvl_ops)) { 647 } else if (unregister_security(&seclvl_ops)) {