diff options
Diffstat (limited to 'kernel/acct.c')
| -rw-r--r-- | kernel/acct.c | 92 | 
1 files changed, 62 insertions, 30 deletions
| diff --git a/kernel/acct.c b/kernel/acct.c index 2e3f4a47e7d0..6312d6bd43e3 100644 --- a/kernel/acct.c +++ b/kernel/acct.c | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | #include <linux/jiffies.h> | 54 | #include <linux/jiffies.h> | 
| 55 | #include <linux/times.h> | 55 | #include <linux/times.h> | 
| 56 | #include <linux/syscalls.h> | 56 | #include <linux/syscalls.h> | 
| 57 | #include <linux/mount.h> | ||
| 57 | #include <asm/uaccess.h> | 58 | #include <asm/uaccess.h> | 
| 58 | #include <asm/div64.h> | 59 | #include <asm/div64.h> | 
| 59 | #include <linux/blkdev.h> /* sector_div */ | 60 | #include <linux/blkdev.h> /* sector_div */ | 
| @@ -192,6 +193,7 @@ static void acct_file_reopen(struct file *file) | |||
| 192 | add_timer(&acct_globals.timer); | 193 | add_timer(&acct_globals.timer); | 
| 193 | } | 194 | } | 
| 194 | if (old_acct) { | 195 | if (old_acct) { | 
| 196 | mnt_unpin(old_acct->f_vfsmnt); | ||
| 195 | spin_unlock(&acct_globals.lock); | 197 | spin_unlock(&acct_globals.lock); | 
| 196 | do_acct_process(0, old_acct); | 198 | do_acct_process(0, old_acct); | 
| 197 | filp_close(old_acct, NULL); | 199 | filp_close(old_acct, NULL); | 
| @@ -199,6 +201,42 @@ static void acct_file_reopen(struct file *file) | |||
| 199 | } | 201 | } | 
| 200 | } | 202 | } | 
| 201 | 203 | ||
| 204 | static int acct_on(char *name) | ||
| 205 | { | ||
| 206 | struct file *file; | ||
| 207 | int error; | ||
| 208 | |||
| 209 | /* Difference from BSD - they don't do O_APPEND */ | ||
| 210 | file = filp_open(name, O_WRONLY|O_APPEND|O_LARGEFILE, 0); | ||
| 211 | if (IS_ERR(file)) | ||
| 212 | return PTR_ERR(file); | ||
| 213 | |||
| 214 | if (!S_ISREG(file->f_dentry->d_inode->i_mode)) { | ||
| 215 | filp_close(file, NULL); | ||
| 216 | return -EACCES; | ||
| 217 | } | ||
| 218 | |||
| 219 | if (!file->f_op->write) { | ||
| 220 | filp_close(file, NULL); | ||
| 221 | return -EIO; | ||
| 222 | } | ||
| 223 | |||
| 224 | error = security_acct(file); | ||
| 225 | if (error) { | ||
| 226 | filp_close(file, NULL); | ||
| 227 | return error; | ||
| 228 | } | ||
| 229 | |||
| 230 | spin_lock(&acct_globals.lock); | ||
| 231 | mnt_pin(file->f_vfsmnt); | ||
| 232 | acct_file_reopen(file); | ||
| 233 | spin_unlock(&acct_globals.lock); | ||
| 234 | |||
| 235 | mntput(file->f_vfsmnt); /* it's pinned, now give up active reference */ | ||
| 236 | |||
| 237 | return 0; | ||
| 238 | } | ||
| 239 | |||
| 202 | /** | 240 | /** | 
| 203 | * sys_acct - enable/disable process accounting | 241 | * sys_acct - enable/disable process accounting | 
| 204 | * @name: file name for accounting records or NULL to shutdown accounting | 242 | * @name: file name for accounting records or NULL to shutdown accounting | 
| @@ -212,47 +250,41 @@ static void acct_file_reopen(struct file *file) | |||
| 212 | */ | 250 | */ | 
| 213 | asmlinkage long sys_acct(const char __user *name) | 251 | asmlinkage long sys_acct(const char __user *name) | 
| 214 | { | 252 | { | 
| 215 | struct file *file = NULL; | ||
| 216 | char *tmp; | ||
| 217 | int error; | 253 | int error; | 
| 218 | 254 | ||
| 219 | if (!capable(CAP_SYS_PACCT)) | 255 | if (!capable(CAP_SYS_PACCT)) | 
| 220 | return -EPERM; | 256 | return -EPERM; | 
| 221 | 257 | ||
| 222 | if (name) { | 258 | if (name) { | 
| 223 | tmp = getname(name); | 259 | char *tmp = getname(name); | 
| 224 | if (IS_ERR(tmp)) { | 260 | if (IS_ERR(tmp)) | 
| 225 | return (PTR_ERR(tmp)); | 261 | return (PTR_ERR(tmp)); | 
| 226 | } | 262 | error = acct_on(tmp); | 
| 227 | /* Difference from BSD - they don't do O_APPEND */ | ||
| 228 | file = filp_open(tmp, O_WRONLY|O_APPEND|O_LARGEFILE, 0); | ||
| 229 | putname(tmp); | 263 | putname(tmp); | 
| 230 | if (IS_ERR(file)) { | 264 | } else { | 
| 231 | return (PTR_ERR(file)); | 265 | error = security_acct(NULL); | 
| 232 | } | 266 | if (!error) { | 
| 233 | if (!S_ISREG(file->f_dentry->d_inode->i_mode)) { | 267 | spin_lock(&acct_globals.lock); | 
| 234 | filp_close(file, NULL); | 268 | acct_file_reopen(NULL); | 
| 235 | return (-EACCES); | 269 | spin_unlock(&acct_globals.lock); | 
| 236 | } | ||
| 237 | |||
| 238 | if (!file->f_op->write) { | ||
| 239 | filp_close(file, NULL); | ||
| 240 | return (-EIO); | ||
| 241 | } | 270 | } | 
| 242 | } | 271 | } | 
| 272 | return error; | ||
| 273 | } | ||
| 243 | 274 | ||
| 244 | error = security_acct(file); | 275 | /** | 
| 245 | if (error) { | 276 | * acct_auto_close - turn off a filesystem's accounting if it is on | 
| 246 | if (file) | 277 | * @m: vfsmount being shut down | 
| 247 | filp_close(file, NULL); | 278 | * | 
| 248 | return error; | 279 | * If the accounting is turned on for a file in the subtree pointed to | 
| 249 | } | 280 | * to by m, turn accounting off. Done when m is about to die. | 
| 250 | 281 | */ | |
| 282 | void acct_auto_close_mnt(struct vfsmount *m) | ||
| 283 | { | ||
| 251 | spin_lock(&acct_globals.lock); | 284 | spin_lock(&acct_globals.lock); | 
| 252 | acct_file_reopen(file); | 285 | if (acct_globals.file && acct_globals.file->f_vfsmnt == m) | 
| 286 | acct_file_reopen(NULL); | ||
| 253 | spin_unlock(&acct_globals.lock); | 287 | spin_unlock(&acct_globals.lock); | 
| 254 | |||
| 255 | return (0); | ||
| 256 | } | 288 | } | 
| 257 | 289 | ||
| 258 | /** | 290 | /** | 
| @@ -266,8 +298,8 @@ void acct_auto_close(struct super_block *sb) | |||
| 266 | { | 298 | { | 
| 267 | spin_lock(&acct_globals.lock); | 299 | spin_lock(&acct_globals.lock); | 
| 268 | if (acct_globals.file && | 300 | if (acct_globals.file && | 
| 269 | acct_globals.file->f_dentry->d_inode->i_sb == sb) { | 301 | acct_globals.file->f_vfsmnt->mnt_sb == sb) { | 
| 270 | acct_file_reopen((struct file *)NULL); | 302 | acct_file_reopen(NULL); | 
| 271 | } | 303 | } | 
| 272 | spin_unlock(&acct_globals.lock); | 304 | spin_unlock(&acct_globals.lock); | 
| 273 | } | 305 | } | 
