diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-14 14:13:11 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2017-11-14 14:13:11 -0800 |
commit | f14fc0ccee5521e5b38cdd1df4385d32c6e1805b (patch) | |
tree | 0d16887967fee217cae343ffebc6666e3fd4265d | |
parent | 23281c8034879c47639ee0f76c34d13ef6beb8ce (diff) | |
parent | 838bee9e756ec46e9b5be25f9e44388d7e185a2a (diff) | |
download | linux-f14fc0ccee5521e5b38cdd1df4385d32c6e1805b.tar.gz linux-f14fc0ccee5521e5b38cdd1df4385d32c6e1805b.tar.bz2 linux-f14fc0ccee5521e5b38cdd1df4385d32c6e1805b.zip |
Merge branch 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs
Pull quota, ext2, isofs and udf fixes from Jan Kara:
- two small quota error handling fixes
- two isofs fixes for architectures with signed char
- several udf block number overflow and signedness fixes
- ext2 rework of mount option handling to avoid GFP_KERNEL allocation
with spinlock held
- ... it also contains a patch to implement auditing of responses to
fanotify permission events. That should have been in the fanotify
pull request but I mistakenly merged that patch into a wrong branch
and noticed only now at which point I don't think it's worth rebasing
and redoing.
* 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jack/linux-fs:
quota: be aware of error from dquot_initialize
quota: fix potential infinite loop
isofs: use unsigned char types consistently
isofs: fix timestamps beyond 2027
udf: Fix some sign-conversion warnings
udf: Fix signed/unsigned format specifiers
udf: Fix 64-bit sign extension issues affecting blocks > 0x7FFFFFFF
udf: Remove some outdate references from documentation
udf: Avoid overflow when session starts at large offset
ext2: Fix possible sleep in atomic during mount option parsing
ext2: Parse mount options into a dedicated structure
audit: Record fanotify access control decisions
-rw-r--r-- | Documentation/filesystems/udf.txt | 8 | ||||
-rw-r--r-- | fs/ext2/super.c | 161 | ||||
-rw-r--r-- | fs/isofs/isofs.h | 22 | ||||
-rw-r--r-- | fs/isofs/rock.h | 64 | ||||
-rw-r--r-- | fs/isofs/util.c | 2 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify.c | 8 | ||||
-rw-r--r-- | fs/notify/fanotify/fanotify_user.c | 16 | ||||
-rw-r--r-- | fs/notify/fdinfo.c | 3 | ||||
-rw-r--r-- | fs/quota/dquot.c | 13 | ||||
-rw-r--r-- | fs/udf/balloc.c | 29 | ||||
-rw-r--r-- | fs/udf/dir.c | 2 | ||||
-rw-r--r-- | fs/udf/directory.c | 9 | ||||
-rw-r--r-- | fs/udf/ialloc.c | 2 | ||||
-rw-r--r-- | fs/udf/inode.c | 50 | ||||
-rw-r--r-- | fs/udf/misc.c | 8 | ||||
-rw-r--r-- | fs/udf/namei.c | 13 | ||||
-rw-r--r-- | fs/udf/partition.c | 6 | ||||
-rw-r--r-- | fs/udf/super.c | 56 | ||||
-rw-r--r-- | fs/udf/truncate.c | 2 | ||||
-rw-r--r-- | fs/udf/udfdecl.h | 21 | ||||
-rw-r--r-- | fs/udf/unicode.c | 2 | ||||
-rw-r--r-- | include/linux/audit.h | 10 | ||||
-rw-r--r-- | include/linux/fsnotify_backend.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/audit.h | 1 | ||||
-rw-r--r-- | include/uapi/linux/fanotify.h | 3 | ||||
-rw-r--r-- | include/uapi/linux/iso_fs.h | 162 | ||||
-rw-r--r-- | kernel/auditsc.c | 6 |
27 files changed, 366 insertions, 314 deletions
diff --git a/Documentation/filesystems/udf.txt b/Documentation/filesystems/udf.txt index 902b95d0ee51..d3d0e3218f86 100644 --- a/Documentation/filesystems/udf.txt +++ b/Documentation/filesystems/udf.txt @@ -1,11 +1,9 @@ * * Documentation/filesystems/udf.txt * -UDF Filesystem version 0.9.8.1 If you encounter problems with reading UDF discs using this driver, -please report them to linux_udf@hpesjro.fc.hp.com, which is the -developer's list. +please report them according to MAINTAINERS file. Write support requires a block driver which supports writing. Currently dvd+rw drives and media support true random sector writes, and so a udf @@ -73,10 +71,8 @@ The following expect a offset from the partition root. For the latest version and toolset see: - http://linux-udf.sourceforge.net/ + https://github.com/pali/udftools Documentation on UDF and ECMA 167 is available FREE from: http://www.osta.org/ http://www.ecma-international.org/ - -Ben Fennema <bfennema@falcon.csc.calpoly.edu> diff --git a/fs/ext2/super.c b/fs/ext2/super.c index 1458706bd2ec..e2b6be03e69b 100644 --- a/fs/ext2/super.c +++ b/fs/ext2/super.c @@ -479,10 +479,10 @@ static const match_table_t tokens = { {Opt_err, NULL} }; -static int parse_options(char *options, struct super_block *sb) +static int parse_options(char *options, struct super_block *sb, + struct ext2_mount_options *opts) { char *p; - struct ext2_sb_info *sbi = EXT2_SB(sb); substring_t args[MAX_OPT_ARGS]; int option; kuid_t uid; @@ -499,16 +499,16 @@ static int parse_options(char *options, struct super_block *sb) token = match_token(p, tokens, args); switch (token) { case Opt_bsd_df: - clear_opt (sbi->s_mount_opt, MINIX_DF); + clear_opt (opts->s_mount_opt, MINIX_DF); break; case Opt_minix_df: - set_opt (sbi->s_mount_opt, MINIX_DF); + set_opt (opts->s_mount_opt, MINIX_DF); break; case Opt_grpid: - set_opt (sbi->s_mount_opt, GRPID); + set_opt (opts->s_mount_opt, GRPID); break; case Opt_nogrpid: - clear_opt (sbi->s_mount_opt, GRPID); + clear_opt (opts->s_mount_opt, GRPID); break; case Opt_resuid: if (match_int(&args[0], &option)) @@ -519,7 +519,7 @@ static int parse_options(char *options, struct super_block *sb) return 0; } - sbi->s_resuid = uid; + opts->s_resuid = uid; break; case Opt_resgid: if (match_int(&args[0], &option)) @@ -529,51 +529,51 @@ static int parse_options(char *options, struct super_block *sb) ext2_msg(sb, KERN_ERR, "Invalid gid value %d", option); return 0; } - sbi->s_resgid = gid; + opts->s_resgid = gid; break; case Opt_sb: /* handled by get_sb_block() instead of here */ /* *sb_block = match_int(&args[0]); */ break; case Opt_err_panic: - clear_opt (sbi->s_mount_opt, ERRORS_CONT); - clear_opt (sbi->s_mount_opt, ERRORS_RO); - set_opt (sbi->s_mount_opt, ERRORS_PANIC); + clear_opt (opts->s_mount_opt, ERRORS_CONT); + clear_opt (opts->s_mount_opt, ERRORS_RO); + set_opt (opts->s_mount_opt, ERRORS_PANIC); break; case Opt_err_ro: - clear_opt (sbi->s_mount_opt, ERRORS_CONT); - clear_opt (sbi->s_mount_opt, ERRORS_PANIC); - set_opt (sbi->s_mount_opt, ERRORS_RO); + clear_opt (opts->s_mount_opt, ERRORS_CONT); + clear_opt (opts->s_mount_opt, ERRORS_PANIC); + set_opt (opts->s_mount_opt, ERRORS_RO); break; case Opt_err_cont: - clear_opt (sbi->s_mount_opt, ERRORS_RO); - clear_opt (sbi->s_mount_opt, ERRORS_PANIC); - set_opt (sbi->s_mount_opt, ERRORS_CONT); + clear_opt (opts->s_mount_opt, ERRORS_RO); + clear_opt (opts->s_mount_opt, ERRORS_PANIC); + set_opt (opts->s_mount_opt, ERRORS_CONT); break; case Opt_nouid32: - set_opt (sbi->s_mount_opt, NO_UID32); + set_opt (opts->s_mount_opt, NO_UID32); break; case Opt_nocheck: - clear_opt (sbi->s_mount_opt, CHECK); + clear_opt (opts->s_mount_opt, CHECK); break; case Opt_debug: - set_opt (sbi->s_mount_opt, DEBUG); + set_opt (opts->s_mount_opt, DEBUG); break; case Opt_oldalloc: - set_opt (sbi->s_mount_opt, OLDALLOC); + set_opt (opts->s_mount_opt, OLDALLOC); break; case Opt_orlov: - clear_opt (sbi->s_mount_opt, OLDALLOC); + clear_opt (opts->s_mount_opt, OLDALLOC); break; case Opt_nobh: - set_opt (sbi->s_mount_opt, NOBH); + set_opt (opts->s_mount_opt, NOBH); break; #ifdef CONFIG_EXT2_FS_XATTR case Opt_user_xattr: - set_opt (sbi->s_mount_opt, XATTR_USER); + set_opt (opts->s_mount_opt, XATTR_USER); break; case Opt_nouser_xattr: - clear_opt (sbi->s_mount_opt, XATTR_USER); + clear_opt (opts->s_mount_opt, XATTR_USER); break; #else case Opt_user_xattr: @@ -584,10 +584,10 @@ static int parse_options(char *options, struct super_block *sb) #endif #ifdef CONFIG_EXT2_FS_POSIX_ACL case Opt_acl: - set_opt(sbi->s_mount_opt, POSIX_ACL); + set_opt(opts->s_mount_opt, POSIX_ACL); break; case Opt_noacl: - clear_opt(sbi->s_mount_opt, POSIX_ACL); + clear_opt(opts->s_mount_opt, POSIX_ACL); break; #else case Opt_acl: @@ -598,13 +598,13 @@ static int parse_options(char *options, struct super_block *sb) #endif case Opt_xip: ext2_msg(sb, KERN_INFO, "use dax instead of xip"); - set_opt(sbi->s_mount_opt, XIP); + set_opt(opts->s_mount_opt, XIP); /* Fall through */ case Opt_dax: #ifdef CONFIG_FS_DAX ext2_msg(sb, KERN_WARNING, "DAX enabled. Warning: EXPERIMENTAL, use at your own risk"); - set_opt(sbi->s_mount_opt, DAX); + set_opt(opts->s_mount_opt, DAX); #else ext2_msg(sb, KERN_INFO, "dax option not supported"); #endif @@ -613,11 +613,11 @@ static int parse_options(char *options, struct super_block *sb) #if defined(CONFIG_QUOTA) case Opt_quota: case Opt_usrquota: - set_opt(sbi->s_mount_opt, USRQUOTA); + set_opt(opts->s_mount_opt, USRQUOTA); break; case Opt_grpquota: - set_opt(sbi->s_mount_opt, GRPQUOTA); + set_opt(opts->s_mount_opt, GRPQUOTA); break; #else case Opt_quota: @@ -629,11 +629,11 @@ static int parse_options(char *options, struct super_block *sb) #endif case Opt_reservation: - set_opt(sbi->s_mount_opt, RESERVATION); + set_opt(opts->s_mount_opt, RESERVATION); ext2_msg(sb, KERN_INFO, "reservations ON"); break; case Opt_noreservation: - clear_opt(sbi->s_mount_opt, RESERVATION); + clear_opt(opts->s_mount_opt, RESERVATION); ext2_msg(sb, KERN_INFO, "reservations OFF"); break; case Opt_ignore: @@ -830,6 +830,7 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) int i, j; __le32 features; int err; + struct ext2_mount_options opts; err = -ENOMEM; sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); @@ -890,35 +891,39 @@ static int ext2_fill_super(struct super_block *sb, void *data, int silent) /* Set defaults before we parse the mount options */ def_mount_opts = le32_to_cpu(es->s_default_mount_opts); if (def_mount_opts & EXT2_DEFM_DEBUG) - set_opt(sbi->s_mount_opt, DEBUG); + set_opt(opts.s_mount_opt, DEBUG); if (def_mount_opts & EXT2_DEFM_BSDGROUPS) - set_opt(sbi->s_mount_opt, GRPID); + set_opt(opts.s_mount_opt, GRPID); if (def_mount_opts & EXT2_DEFM_UID16) - set_opt(sbi->s_mount_opt, NO_UID32); + set_opt(opts.s_mount_opt, NO_UID32); #ifdef CONFIG_EXT2_FS_XATTR if (def_mount_opts & EXT2_DEFM_XATTR_USER) - set_opt(sbi->s_mount_opt, XATTR_USER); + set_opt(opts.s_mount_opt, XATTR_USER); #endif #ifdef CONFIG_EXT2_FS_POSIX_ACL if (def_mount_opts & EXT2_DEFM_ACL) - set_opt(sbi->s_mount_opt, POSIX_ACL); + set_opt(opts.s_mount_opt, POSIX_ACL); #endif if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_PANIC) - set_opt(sbi->s_mount_opt, ERRORS_PANIC); + set_opt(opts.s_mount_opt, ERRORS_PANIC); else if (le16_to_cpu(sbi->s_es->s_errors) == EXT2_ERRORS_CONTINUE) - set_opt(sbi->s_mount_opt, ERRORS_CONT); + set_opt(opts.s_mount_opt, ERRORS_CONT); else - set_opt(sbi->s_mount_opt, ERRORS_RO); + set_opt(opts.s_mount_opt, ERRORS_RO); - sbi->s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid)); - sbi->s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid)); + opts.s_resuid = make_kuid(&init_user_ns, le16_to_cpu(es->s_def_resuid)); + opts.s_resgid = make_kgid(&init_user_ns, le16_to_cpu(es->s_def_resgid)); - set_opt(sbi->s_mount_opt, RESERVATION); + set_opt(opts.s_mount_opt, RESERVATION); - if (!parse_options((char *) data, sb)) + if (!parse_options((char *) data, sb, &opts)) goto failed_mount; + sbi->s_mount_opt = opts.s_mount_opt; + sbi->s_resuid = opts.s_resuid; + sbi->s_resgid = opts.s_resgid; + sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | ((EXT2_SB(sb)->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); @@ -1312,46 +1317,36 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) { struct ext2_sb_info * sbi = EXT2_SB(sb); struct ext2_super_block * es; - struct ext2_mount_options old_opts; - unsigned long old_sb_flags; + struct ext2_mount_options new_opts; int err; sync_filesystem(sb); - spin_lock(&sbi->s_lock); - /* Store the old options */ - old_sb_flags = sb->s_flags; - old_opts.s_mount_opt = sbi->s_mount_opt; - old_opts.s_resuid = sbi->s_resuid; - old_opts.s_resgid = sbi->s_resgid; + spin_lock(&sbi->s_lock); + new_opts.s_mount_opt = sbi->s_mount_opt; + new_opts.s_resuid = sbi->s_resuid; + new_opts.s_resgid = sbi->s_resgid; + spin_unlock(&sbi->s_lock); /* * Allow the "check" option to be passed as a remount option. */ - if (!parse_options(data, sb)) { - err = -EINVAL; - goto restore_opts; - } - - sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | - ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); + if (!parse_options(data, sb, &new_opts)) + return -EINVAL; + spin_lock(&sbi->s_lock); es = sbi->s_es; - if ((sbi->s_mount_opt ^ old_opts.s_mount_opt) & EXT2_MOUNT_DAX) { + if ((sbi->s_mount_opt ^ new_opts.s_mount_opt) & EXT2_MOUNT_DAX) { ext2_msg(sb, KERN_WARNING, "warning: refusing change of " "dax flag with busy inodes while remounting"); - sbi->s_mount_opt ^= EXT2_MOUNT_DAX; - } - if ((bool)(*flags & MS_RDONLY) == sb_rdonly(sb)) { - spin_unlock(&sbi->s_lock); - return 0; + new_opts.s_mount_opt ^= EXT2_MOUNT_DAX; } + if ((bool)(*flags & MS_RDONLY) == sb_rdonly(sb)) + goto out_set; if (*flags & MS_RDONLY) { if (le16_to_cpu(es->s_state) & EXT2_VALID_FS || - !(sbi->s_mount_state & EXT2_VALID_FS)) { - spin_unlock(&sbi->s_lock); - return 0; - } + !(sbi->s_mount_state & EXT2_VALID_FS)) + goto out_set; /* * OK, we are remounting a valid rw partition rdonly, so set @@ -1362,22 +1357,20 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) spin_unlock(&sbi->s_lock); err = dquot_suspend(sb, -1); - if (err < 0) { - spin_lock(&sbi->s_lock); - goto restore_opts; - } + if (err < 0) + return err; ext2_sync_super(sb, es, 1); } else { __le32 ret = EXT2_HAS_RO_COMPAT_FEATURE(sb, ~EXT2_FEATURE_RO_COMPAT_SUPP); if (ret) { + spin_unlock(&sbi->s_lock); ext2_msg(sb, KERN_WARNING, "warning: couldn't remount RDWR because of " "unsupported optional features (%x).", le32_to_cpu(ret)); - err = -EROFS; - goto restore_opts; + return -EROFS; } /* * Mounting a RDONLY partition read-write, so reread and @@ -1394,14 +1387,16 @@ static int ext2_remount (struct super_block * sb, int * flags, char * data) dquot_resume(sb, -1); } - return 0; -restore_opts: - sbi->s_mount_opt = old_opts.s_mount_opt; - sbi->s_resuid = old_opts.s_resuid; - sbi->s_resgid = old_opts.s_resgid; - sb->s_flags = old_sb_flags; + spin_lock(&sbi->s_lock); +out_set: + sbi->s_mount_opt = new_opts.s_mount_opt; + sbi->s_resuid = new_opts.s_resuid; + sbi->s_resgid = new_opts.s_resgid; + sb->s_flags = (sb->s_flags & ~MS_POSIXACL) | + ((sbi->s_mount_opt & EXT2_MOUNT_POSIX_ACL) ? MS_POSIXACL : 0); spin_unlock(&sbi->s_lock); - return err; + + return 0; } static int ext2_statfs (struct dentry * dentry, struct kstatfs * buf) diff --git a/fs/isofs/isofs.h b/fs/isofs/isofs.h index 57d4c3e2e94a..055ec6c586f7 100644 --- a/fs/isofs/isofs.h +++ b/fs/isofs/isofs.h @@ -73,41 +73,41 @@ static inline struct iso_inode_info *ISOFS_I(struct inode *inode) return container_of(inode, struct iso_inode_info, vfs_inode); } -static inline int isonum_711(char *p) +static inline int isonum_711(u8 *p) { - return *(u8 *)p; + return *p; } -static inline int isonum_712(char *p) +static inline int isonum_712(s8 *p) { - return *(s8 *)p; + return *p; } -static inline unsigned int isonum_721(char *p) +static inline unsigned int isonum_721(u8 *p) { return get_unaligned_le16(p); } -static inline unsigned int isonum_722(char *p) +static inline unsigned int isonum_722(u8 *p) { return get_unaligned_be16(p); } -static inline unsigned int isonum_723(char *p) +static inline unsigned int isonum_723(u8 *p) { /* Ignore bigendian datum due to broken mastering programs */ return get_unaligned_le16(p); } -static inline unsigned int isonum_731(char *p) +static inline unsigned int isonum_731(u8 *p) { return get_unaligned_le32(p); } -static inline unsigned int isonum_732(char *p) +static inline unsigned int isonum_732(u8 *p) { return get_unaligned_be32(p); } -static inline unsigned int isonum_733(char *p) +static inline unsigned int isonum_733(u8 *p) { /* Ignore bigendian datum due to broken mastering programs */ return get_unaligned_le32(p); } -extern int iso_date(char *, int); +extern int iso_date(u8 *, int); struct inode; /* To make gcc happy */ diff --git a/fs/isofs/rock.h b/fs/isofs/rock.h index ef03625431bb..1558cf22ef8a 100644 --- a/fs/isofs/rock.h +++ b/fs/isofs/rock.h @@ -7,78 +7,78 @@ */ struct SU_SP_s { - unsigned char magic[2]; - unsigned char skip; + __u8 magic[2]; + __u8 skip; } __attribute__ ((packed)); struct SU_CE_s { - char extent[8]; - char offset[8]; - char size[8]; + __u8 extent[8]; + __u8 offset[8]; + __u8 size[8]; }; struct SU_ER_s { - unsigned char len_id; - unsigned char len_des; - unsigned char len_src; - unsigned char ext_ver; - char data[0]; + __u8 len_id; + __u8 len_des; + __u8 len_src; + __u8 ext_ver; + __u8 data[0]; } __attribute__ ((packed)); struct RR_RR_s { - char flags[1]; + __u8 flags[1]; } __attribute__ ((packed)); struct RR_PX_s { - char mode[8]; - char n_links[8]; - char uid[8]; - char gid[8]; + __u8 mode[8]; + __u8 n_links[8]; + __u8 uid[8]; + __u8 gid[8]; }; struct RR_PN_s { - char dev_high[8]; - char dev_low[8]; + __u8 dev_high[8]; + __u8 dev_low[8]; }; struct SL_component { - unsigned char flags; - unsigned char len; - char text[0]; + __u8 flags; + __u8 len; + __u8 text[0]; } __attribute__ ((packed)); struct RR_SL_s { - unsigned char flags; + __u8 flags; struct SL_component link; } __attribute__ ((packed)); struct RR_NM_s { - unsigned char flags; + __u8 flags; char name[0]; } __attribute__ ((packed)); struct RR_CL_s { - char location[8]; + __u8 location[8]; }; struct RR_PL_s { - char location[8]; + __u8 location[8]; }; struct stamp { - char time[7]; + __u8 time[7]; /* actually 6 unsigned, 1 signed */ } __attribute__ ((packed)); struct RR_TF_s { - char flags; + __u8 flags; struct stamp times[0]; /* Variable number of these beasts */ } __attribute__ ((packed)); /* Linux-specific extension for transparent decompression */ struct RR_ZF_s { - char algorithm[2]; - char parms[2]; - char real_size[8]; + __u8 algorithm[2]; + __u8 parms[2]; + __u8 real_size[8]; }; /* @@ -94,9 +94,9 @@ struct RR_ZF_s { #define TF_LONG_FORM 128 struct rock_ridge { - char signature[2]; - unsigned char len; - unsigned char version; + __u8 signature[2]; + __u8 len; + __u8 version; union { struct SU_SP_s SP; struct SU_CE_s CE; diff --git a/fs/isofs/util.c b/fs/isofs/util.c index 42544bf0e222..e88dba721661 100644 --- a/fs/isofs/util.c +++ b/fs/isofs/util.c @@ -16,7 +16,7 @@ * to GMT. Thus we should always be correct. */ -int iso_date(char * p, int flag) +int iso_date(u8 *p, int flag) { int year, month, day, hour, minute, second, tz; int crtime; diff --git a/fs/notify/fanotify/fanotify.c b/fs/notify/fanotify/fanotify.c index 54cf2d21b547..6702a6a0bbb5 100644 --- a/fs/notify/fanotify/fanotify.c +++ b/fs/notify/fanotify/fanotify.c @@ -10,6 +10,7 @@ #include <linux/sched/user.h> #include <linux/types.h> #include <linux/wait.h> +#include <linux/audit.h> #include "fanotify.h" @@ -65,7 +66,7 @@ static int fanotify_get_response(struct fsnotify_group *group, wait_event(group->fanotify_data.access_waitq, event->response); /* userspace responded, convert to something usable */ - switch (event->response) { + switch (event->response & ~FAN_AUDIT) { case FAN_ALLOW: ret = 0; break; @@ -73,6 +74,11 @@ static int fanotify_get_response(struct fsnotify_group *group, default: ret = -EPERM; } + + /* Check if the response should be audited */ + if (event->response & FAN_AUDIT) + audit_fanotify(event->response & ~FAN_AUDIT); + event->response = 0; pr_debug("%s: group=%p event=%p about to return ret=%d\n", __func__, diff --git a/fs/notify/fanotify/fanotify_user.c b/fs/notify/fanotify/fanotify_user.c index 55499f5a1c96..d0d4bc4c4b70 100644 --- a/fs/notify/fanotify/fanotify_user.c +++ b/fs/notify/fanotify/fanotify_user.c @@ -179,7 +179,7 @@ static int process_access_response(struct fsnotify_group *group, * userspace can send a valid response or we will clean it up after the * timeout */ - switch (response) { + switch (response & ~FAN_AUDIT) { case FAN_ALLOW: case FAN_DENY: break; @@ -190,6 +190,9 @@ static int process_access_response(struct fsnotify_group *group, if (fd < 0) return -EINVAL; + if ((response & FAN_AUDIT) && !group->fanotify_data.audit) + return -EINVAL; + event = dequeue_event(group, fd); if (!event) return -ENOENT; @@ -713,7 +716,11 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) if (!capable(CAP_SYS_ADMIN)) return -EPERM; +#ifdef CONFIG_AUDITSYSCALL + if (flags & ~(FAN_ALL_INIT_FLAGS | FAN_ENABLE_AUDIT)) +#else if (flags & ~FAN_ALL_INIT_FLAGS) +#endif return -EINVAL; if (event_f_flags & ~FANOTIFY_INIT_ALL_EVENT_F_BITS) @@ -795,6 +802,13 @@ SYSCALL_DEFINE2(fanotify_init, unsigned int, flags, unsigned int, event_f_flags) group->fanotify_data.max_marks = FANOTIFY_DEFAULT_MAX_MARKS; } + if (flags & FAN_ENABLE_AUDIT) { + fd = -EPERM; + if (!capable(CAP_AUDIT_WRITE)) + goto out_destroy_group; + group->fanotify_data.audit = true; + } + fd = anon_inode_getfd("[fanotify]", &fanotify_fops, group, f_flags); if (fd < 0) goto out_destroy_group; diff --git a/fs/notify/fdinfo.c b/fs/notify/fdinfo.c index 517f88c1dbe5..d478629c728b 100644 --- a/fs/notify/fdinfo.c +++ b/fs/notify/fdinfo.c @@ -157,6 +157,9 @@ void fanotify_show_fdinfo(struct seq_file *m, struct file *f) if (group->fanotify_data.max_marks == UINT_MAX) flags |= FAN_UNLIMITED_MARKS; + if (group->fanotify_data.audit) + flags |= FAN_ENABLE_AUDIT; + seq_printf(m, "fanotify flags:%x event-flags:%x\n", flags, group->fanotify_data.f_flags); diff --git a/fs/quota/dquot.c b/fs/quota/dquot.c index 9f78b5015f2e..39f1b0b0c76f 100644 --- a/fs/quota/dquot.c +++ b/fs/quota/dquot.c @@ -645,8 +645,15 @@ int dquot_writeback_dquots(struct super_block *sb, int type) spin_unlock(&dq_list_lock); dqstats_inc(DQST_LOOKUPS); err = sb->dq_op->write_dquot(dquot); - if (!ret && err) - ret = err; + if (err) { + /* + * Clear dirty bit anyway to avoid infinite + * loop here. + */ + clear_dquot_dirty(dquot); + if (!ret) + ret = err; + } dqput(dquot); spin_lock(&dq_list_lock); } @@ -2139,7 +2146,7 @@ int dquot_file_open(struct inode *inode, struct file *file) error = generic_file_open(inode, file); if (!error && (file->f_mode & FMODE_WRITE)) - dquot_initialize(inode); + error = dquot_initialize(inode); return error; } EXPORT_SYMBOL(dquot_file_open); diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index e0fd65fe73e8..1b961b1d9699 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c @@ -58,7 +58,7 @@ static int __load_block_bitmap(struct super_block *sb, int nr_groups = bitmap->s_nr_groups; if (block_group >= nr_groups) { - udf_debug("block_group (%d) > nr_groups (%d)\n", + udf_debug("block_group (%u) > nr_groups (%d)\n", block_group, nr_groups); } @@ -122,7 +122,7 @@ static void udf_bitmap_free_blocks(struct super_block *sb, partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; if (bloc->logicalBlockNum + count < count || (bloc->logicalBlockNum + count) > partmap->s_partition_len) { - udf_debug("%d < %d || %d + %d > %d\n", + udf_debug("%u < %d || %u + %u > %u\n", bloc->logicalBlockNum, 0, bloc->logicalBlockNum, count, partmap->s_partition_len); @@ -151,9 +151,9 @@ static void udf_bitmap_free_blocks(struct super_block *sb, bh = bitmap->s_block_bitmap[bitmap_nr]; for (i = 0; i < count; i++) { if (udf_set_bit(bit + i, bh->b_data)) { - udf_debug("bit %ld already set\n", bit + i); + udf_debug("bit %lu already set\n", bit + i); udf_debug("byte=%2x\n", - ((char *)bh->b_data)[(bit + i) >> 3]); + ((__u8 *)bh->b_data)[(bit + i) >> 3]); } } udf_add_free_space(sb, sbi->s_partition, count); @@ -218,16 +218,18 @@ out: return alloc_count; } -static int udf_bitmap_new_block(struct super_block *sb, +static udf_pblk_t udf_bitmap_new_block(struct super_block *sb, struct udf_bitmap *bitmap, uint16_t partition, uint32_t goal, int *err) { struct udf_sb_info *sbi = UDF_SB(sb); - int newbit, bit = 0, block, block_group, group_start; + int newbit, bit = 0; + udf_pblk_t block; + int block_group, group_start; int end_goal, nr_groups, bitmap_nr, i; struct buffer_head *bh = NULL; char *ptr; - int newblock = 0; + udf_pblk_t newblock = 0; *err = -ENOSPC; mutex_lock(&sbi->s_alloc_mutex); @@ -362,7 +364,7 @@ static void udf_table_free_blocks(struct super_block *sb, partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; if (bloc->logicalBlockNum + count < count || (bloc->logicalBlockNum + count) > partmap->s_partition_len) { - udf_debug("%d < %d || %d + %d > %d\n", + udf_debug("%u < %d || %u + %u > %u\n", bloc->logicalBlockNum, 0, bloc->logicalBlockNum, count, partmap->s_partition_len); @@ -515,7 +517,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb, while (first_block != eloc.logicalBlockNum && (etype = udf_next_aext(table, &epos, &eloc, &elen, 1)) != -1) { - udf_debug("eloc=%d, elen=%d, first_block=%d\n", + udf_debug("eloc=%u, elen=%u, first_block=%u\n", eloc.logicalBlockNum, elen, first_block); ; /* empty loop body */ } @@ -545,13 +547,14 @@ static int udf_table_prealloc_blocks(struct super_block *sb, return alloc_count; } -static int udf_table_new_block(struct super_block *sb, +static udf_pblk_t udf_table_new_block(struct super_block *sb, struct inode *table, uint16_t partition, uint32_t goal, int *err) { struct udf_sb_info *sbi = UDF_SB(sb); uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF; - uint32_t newblock = 0, adsize; + udf_pblk_t newblock = 0; + uint32_t adsize; uint32_t elen, goal_elen = 0; struct kernel_lb_addr eloc, uninitialized_var(goal_eloc); struct extent_position epos, goal_epos; @@ -700,12 +703,12 @@ inline int udf_prealloc_blocks(struct super_block *sb, return allocated; } -inline int udf_new_block(struct super_block *sb, +inline udf_pblk_t udf_new_block(struct super_block *sb, struct inode *inode, uint16_t partition, uint32_t goal, int *err) { struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; - int block; + udf_pblk_t block; if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) block = udf_bitmap_new_block(sb, diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 2d0e028067eb..c19dba45aa20 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c @@ -43,7 +43,7 @@ static int udf_readdir(struct file *file, struct dir_context *ctx) struct udf_fileident_bh fibh = { .sbh = NULL, .ebh = NULL}; struct fileIdentDesc *fi = NULL; struct fileIdentDesc cfi; - int block, iblock; + udf_pblk_t block, iblock; loff_t nf_pos; int flen; unsigned char *fname = NULL, *copy_name = NULL; diff --git a/fs/udf/directory.c b/fs/udf/directory.c index 7aa48bd7cbaf..0a98a2369738 100644 --- a/fs/udf/directory.c +++ b/fs/udf/directory.c @@ -26,7 +26,8 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, sector_t *offset) { struct fileIdentDesc *fi; - int i, num, block; + int i, num; + udf_pblk_t block; struct buffer_head *tmp, *bha[16]; struct udf_inode_info *iinfo = UDF_I(dir); @@ -51,7 +52,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, } if (fibh->eoffset == dir->i_sb->s_blocksize) { - int lextoffset = epos->offset; + uint32_t lextoffset = epos->offset; unsigned char blocksize_bits = dir->i_sb->s_blocksize_bits; if (udf_next_aext(dir, epos, eloc, elen, 1) != @@ -110,7 +111,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir |