From 67626ff11d6fa48d77b33f8846a985ebd9a9a228 Mon Sep 17 00:00:00 2001 From: Alain Knaff Date: Mon, 10 Nov 2008 17:08:08 -0800 Subject: [PATCH] --- yaml --- r: 125758 b: refs/heads/master c: 5b6f1eb97d462a45be3b30759758b5fdbb562c8c h: refs/heads/master v: v3 --- [refs] | 2 +- trunk/arch/um/Makefile | 25 +- trunk/arch/um/include/asm/system.h | 14 +- trunk/arch/x86/Kconfig.cpu | 2 +- trunk/drivers/message/i2o/exec-osm.c | 2 +- trunk/drivers/message/i2o/i2o_config.c | 2 +- trunk/drivers/message/i2o/iop.c | 2 +- trunk/drivers/message/i2o/pci.c | 2 +- trunk/drivers/rtc/Kconfig | 6 +- trunk/drivers/rtc/interface.c | 54 -- trunk/drivers/rtc/rtc-dev.c | 51 +- trunk/drivers/video/via/viafbdev.c | 248 ++++----- trunk/fs/affs/file.c | 2 +- trunk/fs/afs/write.c | 2 +- trunk/fs/buffer.c | 4 +- trunk/fs/cifs/file.c | 2 +- trunk/fs/ecryptfs/mmap.c | 2 +- trunk/fs/ext3/inode.c | 2 +- trunk/fs/ext3/namei.c | 3 +- trunk/fs/ext4/ext4_sb.h | 6 - trunk/fs/ext4/inode.c | 4 +- trunk/fs/ext4/namei.c | 3 +- trunk/fs/fuse/file.c | 4 +- trunk/fs/gfs2/ops_address.c | 2 +- trunk/fs/hostfs/hostfs_kern.c | 2 +- trunk/fs/jffs2/file.c | 2 +- trunk/fs/libfs.c | 2 +- trunk/fs/namei.c | 13 +- trunk/fs/nfs/file.c | 2 +- trunk/fs/pipe.c | 7 +- trunk/fs/read_write.c | 13 + trunk/fs/reiserfs/inode.c | 2 +- trunk/fs/smbfs/file.c | 2 +- trunk/fs/ubifs/file.c | 9 +- trunk/include/linux/audit.h | 98 ++-- trunk/include/linux/blockgroup_lock.h | 7 +- trunk/include/linux/ext2_fs_sb.h | 6 - trunk/include/linux/ext3_fs_sb.h | 6 - trunk/include/linux/fs.h | 5 +- trunk/include/linux/pagemap.h | 3 +- trunk/include/linux/radix-tree.h | 2 +- trunk/include/linux/rtc.h | 8 +- trunk/include/linux/spi/spi.h | 2 - trunk/ipc/mqueue.c | 97 ++-- trunk/ipc/sem.c | 2 +- trunk/ipc/shm.c | 4 +- trunk/ipc/util.c | 18 +- trunk/kernel/audit.h | 5 +- trunk/kernel/audit_tree.c | 3 +- trunk/kernel/auditfilter.c | 325 ++++++----- trunk/kernel/auditsc.c | 739 +++++++++++++++---------- trunk/kernel/capability.c | 4 +- trunk/kernel/cgroup.c | 6 +- trunk/mm/filemap.c | 13 +- trunk/mm/mmap.c | 2 +- trunk/mm/mprotect.c | 2 +- trunk/mm/mremap.c | 2 +- trunk/mm/vmalloc.c | 5 +- trunk/net/socket.c | 13 +- trunk/security/selinux/ss/services.c | 26 +- trunk/security/smack/smack_lsm.c | 6 +- 61 files changed, 989 insertions(+), 920 deletions(-) diff --git a/[refs] b/[refs] index 86d67eed8990..17c72ffbd8e0 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: e8c82c2e23e3527e0c9dc195e432c16784d270fa +refs/heads/master: 5b6f1eb97d462a45be3b30759758b5fdbb562c8c diff --git a/trunk/arch/um/Makefile b/trunk/arch/um/Makefile index 0728def32234..d944c343acdb 100644 --- a/trunk/arch/um/Makefile +++ b/trunk/arch/um/Makefile @@ -22,11 +22,10 @@ MODE_INCLUDE += -I$(srctree)/$(ARCH_DIR)/include/shared/skas include $(srctree)/$(ARCH_DIR)/Makefile-skas -SHARED_HEADERS := $(ARCH_DIR)/include/shared -ARCH_INCLUDE := -I$(srctree)/$(SHARED_HEADERS) +ARCH_INCLUDE := -I$(srctree)/$(ARCH_DIR)/include/shared ARCH_INCLUDE += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH)/shared ifneq ($(KBUILD_SRC),) -ARCH_INCLUDE += -I$(SHARED_HEADERS) +ARCH_INCLUDE += -I$(ARCH_DIR)/include/shared # for two generated files endif KBUILD_CPPFLAGS += -I$(srctree)/$(ARCH_DIR)/sys-$(SUBARCH) @@ -86,8 +85,8 @@ endef KBUILD_KCONFIG := arch/um/Kconfig.$(HEADER_ARCH) -archprepare: $(SHARED_HEADERS)/user_constants.h -archprepare: $(SHARED_HEADERS)/kern_constants.h +archprepare: $(ARCH_DIR)/include/shared/user_constants.h +prepare: $(ARCH_DIR)/include/shared/kern_constants.h LINK-$(CONFIG_LD_SCRIPT_STATIC) += -static LINK-$(CONFIG_LD_SCRIPT_DYN) += -Wl,-rpath,/lib @@ -120,13 +119,17 @@ endef # When cleaning we don't include .config, so we don't include # TT or skas makefiles and don't clean skas_ptregs.h. CLEAN_FILES += linux x.i gmon.out \ - $(SHARED_HEADERS)/user_constants.h \ - $(SHARED_HEADERS)/kern_constants.h + $(ARCH_DIR)/include/shared/user_constants.h \ + $(ARCH_DIR)/include/shared/kern_constants.h archclean: @find . \( -name '*.bb' -o -name '*.bbg' -o -name '*.da' \ -o -name '*.gcov' \) -type f -print | xargs rm -f +$(objtree)/$(ARCH_DIR)/include/shared: + @echo ' MKDIR $@' + $(Q)mkdir -p $@ + # Generated files $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s: FORCE @@ -145,11 +148,11 @@ define filechk_gen-asm-offsets echo ""; ) endef -$(SHARED_HEADERS)/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s +$(ARCH_DIR)/include/shared/user_constants.h: $(ARCH_DIR)/sys-$(SUBARCH)/user-offsets.s $(call filechk,gen-asm-offsets) -$(SHARED_HEADERS)/kern_constants.h: - $(Q)mkdir -p $(dir $@) - $(Q)echo '#include "../../../../include/asm/asm-offsets.h"' >$@ +$(ARCH_DIR)/include/shared/kern_constants.h: $(objtree)/$(ARCH_DIR)/include/shared + @echo ' SYMLINK $@' + $(Q)ln -sf ../../../../include/asm/asm-offsets.h $@ export SUBARCH USER_CFLAGS CFLAGS_NO_HARDENING OS HEADER_ARCH DEV_NULL_PATH diff --git a/trunk/arch/um/include/asm/system.h b/trunk/arch/um/include/asm/system.h index 753346e2cdfd..ae5f94d6317d 100644 --- a/trunk/arch/um/include/asm/system.h +++ b/trunk/arch/um/include/asm/system.h @@ -11,21 +11,21 @@ extern int get_signals(void); extern void block_signals(void); extern void unblock_signals(void); -#define local_save_flags(flags) do { typecheck(unsigned long, flags); \ +#define raw_local_save_flags(flags) do { typecheck(unsigned long, flags); \ (flags) = get_signals(); } while(0) -#define local_irq_restore(flags) do { typecheck(unsigned long, flags); \ +#define raw_local_irq_restore(flags) do { typecheck(unsigned long, flags); \ set_signals(flags); } while(0) -#define local_irq_save(flags) do { local_save_flags(flags); \ - local_irq_disable(); } while(0) +#define raw_local_irq_save(flags) do { raw_local_save_flags(flags); \ + raw_local_irq_disable(); } while(0) -#define local_irq_enable() unblock_signals() -#define local_irq_disable() block_signals() +#define raw_local_irq_enable() unblock_signals() +#define raw_local_irq_disable() block_signals() #define irqs_disabled() \ ({ \ unsigned long flags; \ - local_save_flags(flags); \ + raw_local_save_flags(flags); \ (flags == 0); \ }) diff --git a/trunk/arch/x86/Kconfig.cpu b/trunk/arch/x86/Kconfig.cpu index 8078955845ae..85a78575956c 100644 --- a/trunk/arch/x86/Kconfig.cpu +++ b/trunk/arch/x86/Kconfig.cpu @@ -408,7 +408,7 @@ config X86_MINIMUM_CPU_FAMILY config X86_DEBUGCTLMSR def_bool y - depends on !(MK6 || MWINCHIPC6 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) && !UML + depends on !(MK6 || MWINCHIPC6 || MWINCHIP3D || MCYRIXIII || M586MMX || M586TSC || M586 || M486 || M386) menuconfig PROCESSOR_SELECT bool "Supported processor vendors" if EMBEDDED diff --git a/trunk/drivers/message/i2o/exec-osm.c b/trunk/drivers/message/i2o/exec-osm.c index 06c655c55587..56faef1a1d55 100644 --- a/trunk/drivers/message/i2o/exec-osm.c +++ b/trunk/drivers/message/i2o/exec-osm.c @@ -19,7 +19,7 @@ * Auvo Häkkinen * Deepak Saxena * Boji T Kannanthanam - * Alan Cox : + * Alan Cox : * Ported to Linux 2.5. * Markus Lidel : * Minor fixes for 2.6. diff --git a/trunk/drivers/message/i2o/i2o_config.c b/trunk/drivers/message/i2o/i2o_config.c index efba7021948a..f3384c32b9a1 100644 --- a/trunk/drivers/message/i2o/i2o_config.c +++ b/trunk/drivers/message/i2o/i2o_config.c @@ -19,7 +19,7 @@ * Changed ioctl_swdl(), implemented ioctl_swul() and ioctl_swdel() * Deepak Saxena (11/18/1999): * Added event managmenet support - * Alan Cox : + * Alan Cox : * 2.4 rewrite ported to 2.5 * Markus Lidel : * Added pass-thru support for Adaptec's raidutils diff --git a/trunk/drivers/message/i2o/iop.c b/trunk/drivers/message/i2o/iop.c index 35c67d1f255e..6e53a30bfd38 100644 --- a/trunk/drivers/message/i2o/iop.c +++ b/trunk/drivers/message/i2o/iop.c @@ -19,7 +19,7 @@ * Auvo Häkkinen * Deepak Saxena * Boji T Kannanthanam - * Alan Cox : + * Alan Cox : * Ported to Linux 2.5. * Markus Lidel : * Minor fixes for 2.6. diff --git a/trunk/drivers/message/i2o/pci.c b/trunk/drivers/message/i2o/pci.c index 25d6f2341983..610ef1204e68 100644 --- a/trunk/drivers/message/i2o/pci.c +++ b/trunk/drivers/message/i2o/pci.c @@ -19,7 +19,7 @@ * Auvo Häkkinen * Deepak Saxena * Boji T Kannanthanam - * Alan Cox : + * Alan Cox : * Ported to Linux 2.5. * Markus Lidel : * Minor fixes for 2.6. diff --git a/trunk/drivers/rtc/Kconfig b/trunk/drivers/rtc/Kconfig index 165a81843357..123092d8a984 100644 --- a/trunk/drivers/rtc/Kconfig +++ b/trunk/drivers/rtc/Kconfig @@ -102,13 +102,9 @@ config RTC_INTF_DEV_UIE_EMUL depends on RTC_INTF_DEV help Provides an emulation for RTC_UIE if the underlying rtc chip - driver does not expose RTC_UIE ioctls. Those requests generate + driver does not expose RTC_UIE ioctls. Those requests generate once-per-second update interrupts, used for synchronization. - The emulation code will read the time from the hardware - clock several times per second, please enable this option - only if you know that you really need it. - config RTC_DRV_TEST tristate "Test driver/device" help diff --git a/trunk/drivers/rtc/interface.c b/trunk/drivers/rtc/interface.c index fd2c652504ff..a04c1b6b1575 100644 --- a/trunk/drivers/rtc/interface.c +++ b/trunk/drivers/rtc/interface.c @@ -307,60 +307,6 @@ int rtc_set_alarm(struct rtc_device *rtc, struct rtc_wkalrm *alarm) } EXPORT_SYMBOL_GPL(rtc_set_alarm); -int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled) -{ - int err = mutex_lock_interruptible(&rtc->ops_lock); - if (err) - return err; - - if (!rtc->ops) - err = -ENODEV; - else if (!rtc->ops->alarm_irq_enable) - err = -EINVAL; - else - err = rtc->ops->alarm_irq_enable(rtc->dev.parent, enabled); - - mutex_unlock(&rtc->ops_lock); - return err; -} -EXPORT_SYMBOL_GPL(rtc_alarm_irq_enable); - -int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled) -{ - int err = mutex_lock_interruptible(&rtc->ops_lock); - if (err) - return err; - -#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL - if (enabled == 0 && rtc->uie_irq_active) { - mutex_unlock(&rtc->ops_lock); - return rtc_dev_update_irq_enable_emul(rtc, enabled); - } -#endif - - if (!rtc->ops) - err = -ENODEV; - else if (!rtc->ops->update_irq_enable) - err = -EINVAL; - else - err = rtc->ops->update_irq_enable(rtc->dev.parent, enabled); - - mutex_unlock(&rtc->ops_lock); - -#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL - /* - * Enable emulation if the driver did not provide - * the update_irq_enable function pointer or if returned - * -EINVAL to signal that it has been configured without - * interrupts or that are not available at the moment. - */ - if (err == -EINVAL) - err = rtc_dev_update_irq_enable_emul(rtc, enabled); -#endif - return err; -} -EXPORT_SYMBOL_GPL(rtc_update_irq_enable); - /** * rtc_update_irq - report RTC periodic, alarm, and/or update irqs * @rtc: the rtc device diff --git a/trunk/drivers/rtc/rtc-dev.c b/trunk/drivers/rtc/rtc-dev.c index 45152f4952d6..ecdea44ae4e5 100644 --- a/trunk/drivers/rtc/rtc-dev.c +++ b/trunk/drivers/rtc/rtc-dev.c @@ -92,10 +92,10 @@ static void rtc_uie_timer(unsigned long data) spin_unlock_irqrestore(&rtc->irq_lock, flags); } -static int clear_uie(struct rtc_device *rtc) +static void clear_uie(struct rtc_device *rtc) { spin_lock_irq(&rtc->irq_lock); - if (rtc->uie_irq_active) { + if (rtc->irq_active) { rtc->stop_uie_polling = 1; if (rtc->uie_timer_active) { spin_unlock_irq(&rtc->irq_lock); @@ -108,10 +108,9 @@ static int clear_uie(struct rtc_device *rtc) flush_scheduled_work(); spin_lock_irq(&rtc->irq_lock); } - rtc->uie_irq_active = 0; + rtc->irq_active = 0; } spin_unlock_irq(&rtc->irq_lock); - return 0; } static int set_uie(struct rtc_device *rtc) @@ -123,8 +122,8 @@ static int set_uie(struct rtc_device *rtc) if (err) return err; spin_lock_irq(&rtc->irq_lock); - if (!rtc->uie_irq_active) { - rtc->uie_irq_active = 1; + if (!rtc->irq_active) { + rtc->irq_active = 1; rtc->stop_uie_polling = 0; rtc->oldsecs = tm.tm_sec; rtc->uie_task_active = 1; @@ -135,16 +134,6 @@ static int set_uie(struct rtc_device *rtc) spin_unlock_irq(&rtc->irq_lock); return 0; } - -int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, unsigned int enabled) -{ - if (enabled) - return set_uie(rtc); - else - return clear_uie(rtc); -} -EXPORT_SYMBOL(rtc_dev_update_irq_enable_emul); - #endif /* CONFIG_RTC_INTF_DEV_UIE_EMUL */ static ssize_t @@ -368,22 +357,6 @@ static long rtc_dev_ioctl(struct file *file, err = rtc_irq_set_state(rtc, NULL, 0); break; - case RTC_AIE_ON: - mutex_unlock(&rtc->ops_lock); - return rtc_alarm_irq_enable(rtc, 1); - - case RTC_AIE_OFF: - mutex_unlock(&rtc->ops_lock); - return rtc_alarm_irq_enable(rtc, 0); - - case RTC_UIE_ON: - mutex_unlock(&rtc->ops_lock); - return rtc_update_irq_enable(rtc, 1); - - case RTC_UIE_OFF: - mutex_unlock(&rtc->ops_lock); - return rtc_update_irq_enable(rtc, 0); - case RTC_IRQP_SET: err = rtc_irq_set_freq(rtc, NULL, arg); break; @@ -428,6 +401,17 @@ static long rtc_dev_ioctl(struct file *file, err = -EFAULT; return err; +#ifdef CONFIG_RTC_INTF_DEV_UIE_EMUL + case RTC_UIE_OFF: + mutex_unlock(&rtc->ops_lock); + clear_uie(rtc); + return 0; + + case RTC_UIE_ON: + mutex_unlock(&rtc->ops_lock); + err = set_uie(rtc); + return err; +#endif default: err = -ENOTTY; break; @@ -456,10 +440,7 @@ static int rtc_dev_release(struct inode *inode, struct file *file) * Leave the alarm alone; it may be set to trigger a system wakeup * later, or be used by kernel code, and is a one-shot event anyway. */ - - /* Keep ioctl until all drivers are converted */ rtc_dev_ioctl(file, RTC_UIE_OFF, 0); - rtc_update_irq_enable(rtc, 0); rtc_irq_set_state(rtc, NULL, 0); if (rtc->ops->release) diff --git a/trunk/drivers/video/via/viafbdev.c b/trunk/drivers/video/via/viafbdev.c index e21fe5b6f9ff..73ac754ad801 100644 --- a/trunk/drivers/video/via/viafbdev.c +++ b/trunk/drivers/video/via/viafbdev.c @@ -546,25 +546,23 @@ static int viafb_blank(int blank_mode, struct fb_info *info) static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) { - union { - struct viafb_ioctl_mode viamode; - struct viafb_ioctl_samm viasamm; - struct viafb_driver_version driver_version; - struct fb_var_screeninfo sec_var; - struct _panel_size_pos_info panel_pos_size_para; - struct viafb_ioctl_setting viafb_setting; - struct device_t active_dev; - } u; + struct viafb_ioctl_mode viamode; + struct viafb_ioctl_samm viasamm; + struct viafb_driver_version driver_version; + struct fb_var_screeninfo sec_var; + struct _panel_size_pos_info panel_pos_size_para; u32 state_info = 0; + u32 viainfo_size = sizeof(struct viafb_ioctl_info); u32 *viafb_gamma_table; char driver_name[] = "viafb"; u32 __user *argp = (u32 __user *) arg; u32 gpu32; u32 video_dev_info = 0; + struct viafb_ioctl_setting viafb_setting = {}; + struct device_t active_dev = {}; DEBUG_MSG(KERN_INFO "viafb_ioctl: 0x%X !!\n", cmd); - memset(&u, 0, sizeof(u)); switch (cmd) { case VIAFB_GET_CHIP_INFO: @@ -573,7 +571,7 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) return -EFAULT; break; case VIAFB_GET_INFO_SIZE: - return put_user((u32)sizeof(struct viafb_ioctl_info), argp); + return put_user(viainfo_size, argp); case VIAFB_GET_INFO: return viafb_ioctl_get_viafb_info(arg); case VIAFB_HOTPLUG: @@ -586,60 +584,60 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) viafb_hotplug = (gpu32) ? 1 : 0; break; case VIAFB_GET_RESOLUTION: - u.viamode.xres = (u32) viafb_hotplug_Xres; - u.viamode.yres = (u32) viafb_hotplug_Yres; - u.viamode.refresh = (u32) viafb_hotplug_refresh; - u.viamode.bpp = (u32) viafb_hotplug_bpp; + viamode.xres = (u32) viafb_hotplug_Xres; + viamode.yres = (u32) viafb_hotplug_Yres; + viamode.refresh = (u32) viafb_hotplug_refresh; + viamode.bpp = (u32) viafb_hotplug_bpp; if (viafb_SAMM_ON == 1) { - u.viamode.xres_sec = viafb_second_xres; - u.viamode.yres_sec = viafb_second_yres; - u.viamode.virtual_xres_sec = viafb_second_virtual_xres; - u.viamode.virtual_yres_sec = viafb_second_virtual_yres; - u.viamode.refresh_sec = viafb_refresh1; - u.viamode.bpp_sec = viafb_bpp1; + viamode.xres_sec = viafb_second_xres; + viamode.yres_sec = viafb_second_yres; + viamode.virtual_xres_sec = viafb_second_virtual_xres; + viamode.virtual_yres_sec = viafb_second_virtual_yres; + viamode.refresh_sec = viafb_refresh1; + viamode.bpp_sec = viafb_bpp1; } else { - u.viamode.xres_sec = 0; - u.viamode.yres_sec = 0; - u.viamode.virtual_xres_sec = 0; - u.viamode.virtual_yres_sec = 0; - u.viamode.refresh_sec = 0; - u.viamode.bpp_sec = 0; + viamode.xres_sec = 0; + viamode.yres_sec = 0; + viamode.virtual_xres_sec = 0; + viamode.virtual_yres_sec = 0; + viamode.refresh_sec = 0; + viamode.bpp_sec = 0; } - if (copy_to_user(argp, &u.viamode, sizeof(u.viamode))) + if (copy_to_user(argp, &viamode, sizeof(viamode))) return -EFAULT; break; case VIAFB_GET_SAMM_INFO: - u.viasamm.samm_status = viafb_SAMM_ON; + viasamm.samm_status = viafb_SAMM_ON; if (viafb_SAMM_ON == 1) { if (viafb_dual_fb) { - u.viasamm.size_prim = viaparinfo->fbmem_free; - u.viasamm.size_sec = viaparinfo1->fbmem_free; + viasamm.size_prim = viaparinfo->fbmem_free; + viasamm.size_sec = viaparinfo1->fbmem_free; } else { if (viafb_second_size) { - u.viasamm.size_prim = + viasamm.size_prim = viaparinfo->fbmem_free - viafb_second_size * 1024 * 1024; - u.viasamm.size_sec = + viasamm.size_sec = viafb_second_size * 1024 * 1024; } else { - u.viasamm.size_prim = + viasamm.size_prim = viaparinfo->fbmem_free >> 1; - u.viasamm.size_sec = + viasamm.size_sec = (viaparinfo->fbmem_free >> 1); } } - u.viasamm.mem_base = viaparinfo->fbmem; - u.viasamm.offset_sec = viafb_second_offset; + viasamm.mem_base = viaparinfo->fbmem; + viasamm.offset_sec = viafb_second_offset; } else { - u.viasamm.size_prim = + viasamm.size_prim = viaparinfo->memsize - viaparinfo->fbmem_used; - u.viasamm.size_sec = 0; - u.viasamm.mem_base = viaparinfo->fbmem; - u.viasamm.offset_sec = 0; + viasamm.size_sec = 0; + viasamm.mem_base = viaparinfo->fbmem; + viasamm.offset_sec = 0; } - if (copy_to_user(argp, &u.viasamm, sizeof(u.viasamm))) + if (copy_to_user(argp, &viasamm, sizeof(viasamm))) return -EFAULT; break; @@ -664,75 +662,74 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) viafb_lcd_disable(); break; case VIAFB_SET_DEVICE: - if (copy_from_user(&u.active_dev, (void *)argp, - sizeof(u.active_dev))) + if (copy_from_user(&active_dev, (void *)argp, + sizeof(active_dev))) return -EFAULT; - viafb_set_device(u.active_dev); + viafb_set_device(active_dev); viafb_set_par(info); break; case VIAFB_GET_DEVICE: - u.active_dev.crt = viafb_CRT_ON; - u.active_dev.dvi = viafb_DVI_ON; - u.active_dev.lcd = viafb_LCD_ON; - u.active_dev.samm = viafb_SAMM_ON; - u.active_dev.primary_dev = viafb_primary_dev; + active_dev.crt = viafb_CRT_ON; + active_dev.dvi = viafb_DVI_ON; + active_dev.lcd = viafb_LCD_ON; + active_dev.samm = viafb_SAMM_ON; + active_dev.primary_dev = viafb_primary_dev; - u.active_dev.lcd_dsp_cent = viafb_lcd_dsp_method; - u.active_dev.lcd_panel_id = viafb_lcd_panel_id; - u.active_dev.lcd_mode = viafb_lcd_mode; + active_dev.lcd_dsp_cent = viafb_lcd_dsp_method; + active_dev.lcd_panel_id = viafb_lcd_panel_id; + active_dev.lcd_mode = viafb_lcd_mode; - u.active_dev.xres = viafb_hotplug_Xres; - u.active_dev.yres = viafb_hotplug_Yres; + active_dev.xres = viafb_hotplug_Xres; + active_dev.yres = viafb_hotplug_Yres; - u.active_dev.xres1 = viafb_second_xres; - u.active_dev.yres1 = viafb_second_yres; + active_dev.xres1 = viafb_second_xres; + active_dev.yres1 = viafb_second_yres; - u.active_dev.bpp = viafb_bpp; - u.active_dev.bpp1 = viafb_bpp1; - u.active_dev.refresh = viafb_refresh; - u.active_dev.refresh1 = viafb_refresh1; + active_dev.bpp = viafb_bpp; + active_dev.bpp1 = viafb_bpp1; + active_dev.refresh = viafb_refresh; + active_dev.refresh1 = viafb_refresh1; - u.active_dev.epia_dvi = viafb_platform_epia_dvi; - u.active_dev.lcd_dual_edge = viafb_device_lcd_dualedge; - u.active_dev.bus_width = viafb_bus_width; + active_dev.epia_dvi = viafb_platform_epia_dvi; + active_dev.lcd_dual_edge = viafb_device_lcd_dualedge; + active_dev.bus_width = viafb_bus_width; - if (copy_to_user(argp, &u.active_dev, sizeof(u.active_dev))) + if (copy_to_user(argp, &active_dev, sizeof(active_dev))) return -EFAULT; break; case VIAFB_GET_DRIVER_VERSION: - u.driver_version.iMajorNum = VERSION_MAJOR; - u.driver_version.iKernelNum = VERSION_KERNEL; - u.driver_version.iOSNum = VERSION_OS; - u.driver_version.iMinorNum = VERSION_MINOR; + driver_version.iMajorNum = VERSION_MAJOR; + driver_version.iKernelNum = VERSION_KERNEL; + driver_version.iOSNum = VERSION_OS; + driver_version.iMinorNum = VERSION_MINOR; - if (copy_to_user(argp, &u.driver_version, - sizeof(u.driver_version))) + if (copy_to_user(argp, &driver_version, + sizeof(driver_version))) return -EFAULT; break; case VIAFB_SET_DEVICE_INFO: - if (copy_from_user(&u.viafb_setting, - argp, sizeof(u.viafb_setting))) + if (copy_from_user(&viafb_setting, + argp, sizeof(viafb_setting))) return -EFAULT; - if (apply_device_setting(u.viafb_setting, info) < 0) + if (apply_device_setting(viafb_setting, info) < 0) return -EINVAL; break; case VIAFB_SET_SECOND_MODE: - if (copy_from_user(&u.sec_var, argp, sizeof(u.sec_var))) + if (copy_from_user(&sec_var, argp, sizeof(sec_var))) return -EFAULT; - apply_second_mode_setting(&u.sec_var); + apply_second_mode_setting(&sec_var); break; case VIAFB_GET_DEVICE_INFO: - retrieve_device_setting(&u.viafb_setting); + retrieve_device_setting(&viafb_setting); - if (copy_to_user(argp, &u.viafb_setting, - sizeof(u.viafb_setting))) + if (copy_to_user(argp, &viafb_setting, sizeof(viafb_setting))) return -EFAULT; break; @@ -809,51 +806,51 @@ static int viafb_ioctl(struct fb_info *info, u_int cmd, u_long arg) break; case VIAFB_GET_PANEL_MAX_SIZE: - if (copy_from_user(&u.panel_pos_size_para, argp, - sizeof(u.panel_pos_size_para))) + if (copy_from_user + (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) return -EFAULT; - u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; - if (copy_to_user(argp, &u.panel_pos_size_para, - sizeof(u.panel_pos_size_para))) + panel_pos_size_para.x = panel_pos_size_para.y = 0; + if (copy_to_user(argp, &panel_pos_size_para, + sizeof(panel_pos_size_para))) return -EFAULT; break; case VIAFB_GET_PANEL_MAX_POSITION: - if (copy_from_user(&u.panel_pos_size_para, argp, - sizeof(u.panel_pos_size_para))) + if (copy_from_user + (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) return -EFAULT; - u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; - if (copy_to_user(argp, &u.panel_pos_size_para, - sizeof(u.panel_pos_size_para))) + panel_pos_size_para.x = panel_pos_size_para.y = 0; + if (copy_to_user(argp, &panel_pos_size_para, + sizeof(panel_pos_size_para))) return -EFAULT; break; case VIAFB_GET_PANEL_POSITION: - if (copy_from_user(&u.panel_pos_size_para, argp, - sizeof(u.panel_pos_size_para))) + if (copy_from_user + (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) return -EFAULT; - u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; - if (copy_to_user(argp, &u.panel_pos_size_para, - sizeof(u.panel_pos_size_para))) + panel_pos_size_para.x = panel_pos_size_para.y = 0; + if (copy_to_user(argp, &panel_pos_size_para, + sizeof(panel_pos_size_para))) return -EFAULT; break; case VIAFB_GET_PANEL_SIZE: - if (copy_from_user(&u.panel_pos_size_para, argp, - sizeof(u.panel_pos_size_para))) + if (copy_from_user + (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) return -EFAULT; - u.panel_pos_size_para.x = u.panel_pos_size_para.y = 0; - if (copy_to_user(argp, &u.panel_pos_size_para, - sizeof(u.panel_pos_size_para))) + panel_pos_size_para.x = panel_pos_size_para.y = 0; + if (copy_to_user(argp, &panel_pos_size_para, + sizeof(panel_pos_size_para))) return -EFAULT; break; case VIAFB_SET_PANEL_POSITION: - if (copy_from_user(&u.panel_pos_size_para, argp, - sizeof(u.panel_pos_size_para))) + if (copy_from_user + (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) return -EFAULT; break; case VIAFB_SET_PANEL_SIZE: - if (copy_from_user(&u.panel_pos_size_para, argp, - sizeof(u.panel_pos_size_para))) + if (copy_from_user + (&panel_pos_size_para, argp, sizeof(panel_pos_size_para))) return -EFAULT; break; @@ -1055,8 +1052,10 @@ static void viafb_imageblit(struct fb_info *info, static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) { + u8 data[CURSOR_SIZE / 8]; + u32 data_bak[CURSOR_SIZE / 32]; u32 temp, xx, yy, bg_col = 0, fg_col = 0; - int i, j = 0; + int size, i, j = 0; static int hw_cursor; struct viafb_par *p_viafb_par; @@ -1179,29 +1178,22 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) } if (cursor->set & FB_CUR_SETSHAPE) { - struct { - u8 data[CURSOR_SIZE / 8]; - u32 bak[CURSOR_SIZE / 32]; - } *cr_data = kzalloc(sizeof(*cr_data), GFP_ATOMIC); - int size = + size = ((viacursor.image.width + 7) >> 3) * viacursor.image.height; - if (cr_data == NULL) - goto out; - if (MAX_CURS == 32) { for (i = 0; i < (CURSOR_SIZE / 32); i++) { - cr_data->bak[i] = 0x0; - cr_data->bak[i + 1] = 0xFFFFFFFF; + data_bak[i] = 0x0; + data_bak[i + 1] = 0xFFFFFFFF; i += 1; } } else if (MAX_CURS == 64) { for (i = 0; i < (CURSOR_SIZE / 32); i++) { - cr_data->bak[i] = 0x0; - cr_data->bak[i + 1] = 0x0; - cr_data->bak[i + 2] = 0xFFFFFFFF; - cr_data->bak[i + 3] = 0xFFFFFFFF; + data_bak[i] = 0x0; + data_bak[i + 1] = 0x0; + data_bak[i + 2] = 0xFFFFFFFF; + data_bak[i + 3] = 0xFFFFFFFF; i += 3; } } @@ -1209,12 +1201,12 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) switch (viacursor.rop) { case ROP_XOR: for (i = 0; i < size; i++) - cr_data->data[i] = viacursor.mask[i]; + data[i] = viacursor.mask[i]; break; case ROP_COPY: for (i = 0; i < size; i++) - cr_data->data[i] = viacursor.mask[i]; + data[i] = viacursor.mask[i]; break; default: break; @@ -1222,25 +1214,23 @@ static int viafb_cursor(struct fb_info *info, struct fb_cursor *cursor) if (MAX_CURS == 32) { for (i = 0; i < size; i++) { - cr_data->bak[j] = (u32) cr_data->data[i]; - cr_data->bak[j + 1] = ~cr_data->bak[j]; + data_bak[j] = (u32) data[i]; + data_bak[j + 1] = ~data_bak[j]; j += 2; } } else if (MAX_CURS == 64) { for (i = 0; i < size; i++) { - cr_data->bak[j] = (u32) cr_data->data[i]; - cr_data->bak[j + 1] = 0x0; - cr_data->bak[j + 2] = ~cr_data->bak[j]; - cr_data->bak[j + 3] = ~cr_data->bak[j + 1]; + data_bak[j] = (u32) data[i]; + data_bak[j + 1] = 0x0; + data_bak[j + 2] = ~data_bak[j]; + data_bak[j + 3] = ~data_bak[j + 1]; j += 4; } } memcpy(((struct viafb_par *)(info->par))->fbmem_virt + ((struct viafb_par *)(info->par))->cursor_start, - cr_data->bak, CURSOR_SIZE); -out: - kfree(cr_data); + data_bak, CURSOR_SIZE); } if (viacursor.enable) diff --git a/trunk/fs/affs/file.c b/trunk/fs/affs/file.c index 9246cb4aa018..1377b1240b6e 100644 --- a/trunk/fs/affs/file.c +++ b/trunk/fs/affs/file.c @@ -628,7 +628,7 @@ static int affs_write_begin_ofs(struct file *file, struct address_space *mapping } index = pos >> PAGE_CACHE_SHIFT; - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) return -ENOMEM; *pagep = page; diff --git a/trunk/fs/afs/write.c b/trunk/fs/afs/write.c index 3fb36d433621..d6b85dab35fc 100644 --- a/trunk/fs/afs/write.c +++ b/trunk/fs/afs/write.c @@ -144,7 +144,7 @@ int afs_write_begin(struct file *file, struct address_space *mapping, candidate->state = AFS_WBACK_PENDING; init_waitqueue_head(&candidate->waitq); - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) { kfree(candidate); return -ENOMEM; diff --git a/trunk/fs/buffer.c b/trunk/fs/buffer.c index a13f09b696f7..776ae091d3b0 100644 --- a/trunk/fs/buffer.c +++ b/trunk/fs/buffer.c @@ -1996,7 +1996,7 @@ int block_write_begin(struct file *file, struct address_space *mapping, page = *pagep; if (page == NULL) { ownpage = 1; - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) { status = -ENOMEM; goto out; @@ -2502,7 +2502,7 @@ int nobh_write_begin(struct file *file, struct address_space *mapping, from = pos & (PAGE_CACHE_SIZE - 1); to = from + len; - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) return -ENOMEM; *pagep = page; diff --git a/trunk/fs/cifs/file.c b/trunk/fs/cifs/file.c index 12bb656fbe75..b1e1fc6a6e6a 100644 --- a/trunk/fs/cifs/file.c +++ b/trunk/fs/cifs/file.c @@ -2074,7 +2074,7 @@ static int cifs_write_begin(struct file *file, struct address_space *mapping, cFYI(1, ("write_begin from %lld len %d", (long long)pos, len)); - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) { rc = -ENOMEM; goto out; diff --git a/trunk/fs/ecryptfs/mmap.c b/trunk/fs/ecryptfs/mmap.c index 46cec2b69796..04d7b3fa1ac6 100644 --- a/trunk/fs/ecryptfs/mmap.c +++ b/trunk/fs/ecryptfs/mmap.c @@ -288,7 +288,7 @@ static int ecryptfs_write_begin(struct file *file, loff_t prev_page_end_size; int rc = 0; - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) return -ENOMEM; *pagep = page; diff --git a/trunk/fs/ext3/inode.c b/trunk/fs/ext3/inode.c index 5fa453b49a64..c4bdccf976b5 100644 --- a/trunk/fs/ext3/inode.c +++ b/trunk/fs/ext3/inode.c @@ -1161,7 +1161,7 @@ static int ext3_write_begin(struct file *file, struct address_space *mapping, to = from + len; retry: - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) return -ENOMEM; *pagep = page; diff --git a/trunk/fs/ext3/namei.c b/trunk/fs/ext3/namei.c index 1dd2abe6313e..297ea8dfac7c 100644 --- a/trunk/fs/ext3/namei.c +++ b/trunk/fs/ext3/namei.c @@ -2175,7 +2175,8 @@ static int ext3_symlink (struct inode * dir, * We have a transaction open. All is sweetness. It also sets * i_size in generic_commit_write(). */ - err = __page_symlink(inode, symname, l, 1); + err = __page_symlink(inode, symname, l, + mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); if (err) { drop_nlink(inode); unlock_new_inode(inode); diff --git a/trunk/fs/ext4/ext4_sb.h b/trunk/fs/ext4/ext4_sb.h index b21f16713db0..445fde603df8 100644 --- a/trunk/fs/ext4/ext4_sb.h +++ b/trunk/fs/ext4/ext4_sb.h @@ -146,10 +146,4 @@ struct ext4_sb_info { struct flex_groups *s_flex_groups; }; -static inline spinlock_t * -sb_bgl_lock(struct ext4_sb_info *sbi, unsigned int block_group) -{ - return bgl_lock_ptr(&sbi->s_blockgroup_lock, block_group); -} - #endif /* _EXT4_SB */ diff --git a/trunk/fs/ext4/inode.c b/trunk/fs/ext4/inode.c index 6702a49992a6..7c3325e0b005 100644 --- a/trunk/fs/ext4/inode.c +++ b/trunk/fs/ext4/inode.c @@ -1346,7 +1346,7 @@ static int ext4_write_begin(struct file *file, struct address_space *mapping, goto out; } - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) { ext4_journal_stop(handle); ret = -ENOMEM; @@ -2550,7 +2550,7 @@ static int ext4_da_write_begin(struct file *file, struct address_space *mapping, goto out; } - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) { ext4_journal_stop(handle); ret = -ENOMEM; diff --git a/trunk/fs/ext4/namei.c b/trunk/fs/ext4/namei.c index 9fd2a5e1be4d..da98a9012fa5 100644 --- a/trunk/fs/ext4/namei.c +++ b/trunk/fs/ext4/namei.c @@ -2212,7 +2212,8 @@ static int ext4_symlink(struct inode *dir, * We have a transaction open. All is sweetness. It also sets * i_size in generic_commit_write(). */ - err = __page_symlink(inode, symname, l, 1); + err = __page_symlink(inode, symname, l, + mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); if (err) { clear_nlink(inode); unlock_new_inode(inode); diff --git a/trunk/fs/fuse/file.c b/trunk/fs/fuse/file.c index 4c9ee7011265..34930a964b82 100644 --- a/trunk/fs/fuse/file.c +++ b/trunk/fs/fuse/file.c @@ -646,7 +646,7 @@ static int fuse_write_begin(struct file *file, struct address_space *mapping, { pgoff_t index = pos >> PAGE_CACHE_SHIFT; - *pagep = grab_cache_page_write_begin(mapping, index, flags); + *pagep = __grab_cache_page(mapping, index); if (!*pagep) return -ENOMEM; return 0; @@ -779,7 +779,7 @@ static ssize_t fuse_fill_write_pages(struct fuse_req *req, break; err = -ENOMEM; - page = grab_cache_page_write_begin(mapping, index, 0); + page = __grab_cache_page(mapping, index); if (!page) break; diff --git a/trunk/fs/gfs2/ops_address.c b/trunk/fs/gfs2/ops_address.c index 15f710f2d4da..27563816e1c5 100644 --- a/trunk/fs/gfs2/ops_address.c +++ b/trunk/fs/gfs2/ops_address.c @@ -675,7 +675,7 @@ static int gfs2_write_begin(struct file *file, struct address_space *mapping, goto out_trans_fail; error = -ENOMEM; - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); *pagep = page; if (unlikely(!page)) goto out_endtrans; diff --git a/trunk/fs/hostfs/hostfs_kern.c b/trunk/fs/hostfs/hostfs_kern.c index 5c538e0ec14b..3a31451ac170 100644 --- a/trunk/fs/hostfs/hostfs_kern.c +++ b/trunk/fs/hostfs/hostfs_kern.c @@ -501,7 +501,7 @@ int hostfs_write_begin(struct file *file, struct address_space *mapping, { pgoff_t index = pos >> PAGE_CACHE_SHIFT; - *pagep = grab_cache_page_write_begin(mapping, index, flags); + *pagep = __grab_cache_page(mapping, index); if (!*pagep) return -ENOMEM; return 0; diff --git a/trunk/fs/jffs2/file.c b/trunk/fs/jffs2/file.c index 5edc2bf20581..5a98aa87c853 100644 --- a/trunk/fs/jffs2/file.c +++ b/trunk/fs/jffs2/file.c @@ -132,7 +132,7 @@ static int jffs2_write_begin(struct file *filp, struct address_space *mapping, uint32_t pageofs = index << PAGE_CACHE_SHIFT; int ret = 0; - pg = grab_cache_page_write_begin(mapping, index, flags); + pg = __grab_cache_page(mapping, index); if (!pg) return -ENOMEM; *pagep = pg; diff --git a/trunk/fs/libfs.c b/trunk/fs/libfs.c index bdaec17fa388..e960a8321902 100644 --- a/trunk/fs/libfs.c +++ b/trunk/fs/libfs.c @@ -360,7 +360,7 @@ int simple_write_begin(struct file *file, struct address_space *mapping, index = pos >> PAGE_CACHE_SHIFT; from = pos & (PAGE_CACHE_SIZE - 1); - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) return -ENOMEM; diff --git a/trunk/fs/namei.c b/trunk/fs/namei.c index df2d3df4f049..dd5c9f0bf829 100644 --- a/trunk/fs/namei.c +++ b/trunk/fs/namei.c @@ -2817,23 +2817,18 @@ void page_put_link(struct dentry *dentry, struct nameidata *nd, void *cookie) } } -/* - * The nofs argument instructs pagecache_write_begin to pass AOP_FLAG_NOFS - */ -int __page_symlink(struct inode *inode, const char *symname, int len, int nofs) +int __page_symlink(struct inode *inode, const char *symname, int len, + gfp_t gfp_mask) { struct address_space *mapping = inode->i_mapping; struct page *page; void *fsdata; int err; char *kaddr; - unsigned int flags = AOP_FLAG_UNINTERRUPTIBLE; - if (nofs) - flags |= AOP_FLAG_NOFS; retry: err = pagecache_write_begin(NULL, mapping, 0, len-1, - flags, &page, &fsdata); + AOP_FLAG_UNINTERRUPTIBLE, &page, &fsdata); if (err) goto fail; @@ -2857,7 +2852,7 @@ int __page_symlink(struct inode *inode, const char *symname, int len, int nofs) int page_symlink(struct inode *inode, const char *symname, int len) { return __page_symlink(inode, symname, len, - !(mapping_gfp_mask(inode->i_mapping) & __GFP_FS)); + mapping_gfp_mask(inode->i_mapping)); } const struct inode_operations page_symlink_inode_operations = { diff --git a/trunk/fs/nfs/file.c b/trunk/fs/nfs/file.c index 90f292b520d2..d319b49f8f06 100644 --- a/trunk/fs/nfs/file.c +++ b/trunk/fs/nfs/file.c @@ -354,7 +354,7 @@ static int nfs_write_begin(struct file *file, struct address_space *mapping, file->f_path.dentry->d_name.name, mapping->host->i_ino, len, (long long) pos); - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) return -ENOMEM; *pagep = page; diff --git a/trunk/fs/pipe.c b/trunk/fs/pipe.c index 891697112f66..aaf797bd57b9 100644 --- a/trunk/fs/pipe.c +++ b/trunk/fs/pipe.c @@ -1016,7 +1016,10 @@ int do_pipe_flags(int *fd, int flags) goto err_fdr; fdw = error; - audit_fd_pair(fdr, fdw); + error = audit_fd_pair(fdr, fdw); + if (error < 0) + goto err_fdw; + fd_install(fdr, fr); fd_install(fdw, fw); fd[0] = fdr; @@ -1024,6 +1027,8 @@ int do_pipe_flags(int *fd, int flags) return 0; + err_fdw: + put_unused_fd(fdw); err_fdr: put_unused_fd(fdr); err_read_pipe: diff --git a/trunk/fs/read_write.c b/trunk/fs/read_write.c index 969a6d9c020b..5cc6924eb158 100644 --- a/trunk/fs/read_write.c +++ b/trunk/fs/read_write.c @@ -50,6 +50,14 @@ generic_file_llseek_unlocked(struct file *file, loff_t offset, int origin) offset += inode->i_size; break; case SEEK_CUR: + /* + * Here we special-case the lseek(fd, 0, SEEK_CUR) + * position-querying operation. Avoid rewriting the "same" + * f_pos value back to the file because a concurrent read(), + * write() or lseek() might have altered it + */ + if (offset == 0) + return file->f_pos; offset += file->f_pos; break; } @@ -105,6 +113,10 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin) offset += i_size_read(file->f_path.dentry->d_inode); break; case SEEK_CUR: + if (offset == 0) { + retval = file->f_pos; + goto out; + } offset += file->f_pos; } retval = -EINVAL; @@ -115,6 +127,7 @@ loff_t default_llseek(struct file *file, loff_t offset, int origin) } retval = offset; } +out: unlock_kernel(); return retval; } diff --git a/trunk/fs/reiserfs/inode.c b/trunk/fs/reiserfs/inode.c index ed04f47007f8..145c2d3e5e01 100644 --- a/trunk/fs/reiserfs/inode.c +++ b/trunk/fs/reiserfs/inode.c @@ -2561,7 +2561,7 @@ static int reiserfs_write_begin(struct file *file, } index = pos >> PAGE_CACHE_SHIFT; - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (!page) return -ENOMEM; *pagep = page; diff --git a/trunk/fs/smbfs/file.c b/trunk/fs/smbfs/file.c index 92d5e8ffb639..e4f8d51a5553 100644 --- a/trunk/fs/smbfs/file.c +++ b/trunk/fs/smbfs/file.c @@ -297,7 +297,7 @@ static int smb_write_begin(struct file *file, struct address_space *mapping, struct page **pagep, void **fsdata) { pgoff_t index = pos >> PAGE_CACHE_SHIFT; - *pagep = grab_cache_page_write_begin(mapping, index, flags); + *pagep = __grab_cache_page(mapping, index); if (!*pagep) return -ENOMEM; return 0; diff --git a/trunk/fs/ubifs/file.c b/trunk/fs/ubifs/file.c index bf37374567fa..fe82d2464d46 100644 --- a/trunk/fs/ubifs/file.c +++ b/trunk/fs/ubifs/file.c @@ -219,8 +219,7 @@ static void release_existing_page_budget(struct ubifs_info *c) } static int write_begin_slow(struct address_space *mapping, - loff_t pos, unsigned len, struct page **pagep, - unsigned flags) + loff_t pos, unsigned len, struct page **pagep) { struct inode *inode = mapping->host; struct ubifs_info *c = inode->i_sb->s_fs_info; @@ -248,7 +247,7 @@ static int write_begin_slow(struct address_space *mapping, if (unlikely(err)) return err; - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (unlikely(!page)) { ubifs_release_budget(c, &req); return -ENOMEM; @@ -439,7 +438,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping, return -EROFS; /* Try out the fast-path part first */ - page = grab_cache_page_write_begin(mapping, index, flags); + page = __grab_cache_page(mapping, index); if (unlikely(!page)) return -ENOMEM; @@ -484,7 +483,7 @@ static int ubifs_write_begin(struct file *file, struct address_space *mapping, unlock_page(page); page_cache_release(page); - return write_begin_slow(mapping, pos, len, pagep, flags); + return write_begin_slow(mapping, pos, len, pagep); } /* diff --git a/trunk/include/linux/audit.h b/trunk/include/linux/audit.h index 67e5dbfc2961..26c4f6f65a46 100644 --- a/trunk/include/linux/audit.h +++ b/trunk/include/linux/audit.h @@ -247,18 +247,6 @@ #define AUDIT_GREATER_THAN_OR_EQUAL (AUDIT_GREATER_THAN|AUDIT_EQUAL) #define AUDIT_OPERATORS (AUDIT_EQUAL|AUDIT_NOT_EQUAL|AUDIT_BIT_MASK) -enum { - Audit_equal, - Audit_not_equal, - Audit_bitmask, - Audit_bittest, - Audit_lt, - Audit_gt, - Audit_le, - Audit_ge, - Audit_bad -}; - /* Status symbols */ /* Mask values */ #define AUDIT_STATUS_ENABLED 0x0001 @@ -385,8 +373,6 @@ struct audit_krule { struct audit_watch *watch; /* associated watch */ struct audit_tree *tree; /* associated watched tree */ struct list_head rlist; /* entry in audit_{watch,tree}.rules list */ - struct list_head list; /* for AUDIT_LIST* purposes only */ - u64 prio; }; struct audit_field { @@ -457,56 +443,70 @@ extern int audit_set_loginuid(struct task_struct *task, uid_t loginuid); #define audit_get_loginuid(t) ((t)->loginuid) #define audit_get_sessionid(t) ((t)->sessionid) extern void audit_log_task_context(struct audit_buffer *ab); -extern void __audit_ipc_obj(struct kern_ipc_perm *ipcp); -extern void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); +extern int __audit_ipc_obj(struct kern_ipc_perm *ipcp); +extern int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode); extern int audit_bprm(struct linux_binprm *bprm); -extern void audit_socketcall(int nargs, unsigned long *args); +extern int audit_socketcall(int nargs, unsigned long *args); extern int audit_sockaddr(int len, void *addr); -extern void __audit_fd_pair(int fd1, int fd2); +extern int __audit_fd_pair(int fd1, int fd2); extern int audit_set_macxattr(const char *name); -extern void __audit_mq_open(int oflag, mode_t mode, struct mq_attr *attr); -extern void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout); -extern void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification); -extern void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat); +extern int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr); +extern int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout); +extern int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout); +extern int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification); +extern int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat); extern int __audit_log_bprm_fcaps(struct linux_binprm *bprm, const struct cred *new, const struct cred *old); -extern void __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old); +extern int __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old); -static inline void audit_ipc_obj(struct kern_ipc_perm *ipcp) +static inline int audit_ipc_obj(struct kern_ipc_perm *ipcp) { if (unlikely(!audit_dummy_context())) - __audit_ipc_obj(ipcp); + return __audit_ipc_obj(ipcp); + return 0; +} +static inline int audit_fd_pair(int fd1, int fd2) +{ + if (unlikely(!audit_dummy_context())) + return __audit_fd_pair(fd1, fd2); + return 0; } -static inline void audit_fd_pair(int fd1, int fd2) +static inline int audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) { if (unlikely(!audit_dummy_context())) - __audit_fd_pair(fd1, fd2); + return __audit_ipc_set_perm(qbytes, uid, gid, mode); + return 0; } -static inline void audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) +static inline int audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr) { if (unlikely(!audit_dummy_context())) - __audit_ipc_set_perm(qbytes, uid, gid, mode); + return __audit_mq_open(oflag, mode, u_attr); + return 0; } -static inline void audit_mq_open(int oflag, mode_t mode, struct mq_attr *attr) +static inline int audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec __user *u_abs_timeout) { if (unlikely(!audit_dummy_context())) - __audit_mq_open(oflag, mode, attr); + return __audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout); + return 0; } -static inline void audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, const struct timespec *abs_timeout) +static inline int audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, unsigned int __user *u_msg_prio, const struct timespec __user *u_abs_timeout) { if (unlikely(!audit_dummy_context())) - __audit_mq_sendrecv(mqdes, msg_len, msg_prio, abs_timeout); + return __audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout); + return 0; } -static inline void audit_mq_notify(mqd_t mqdes, const struct sigevent *notification) +static inline int audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification) { if (unlikely(!audit_dummy_context())) - __audit_mq_notify(mqdes, notification); + return __audit_mq_notify(mqdes, u_notification); + return 0; } -static inline void audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) +static inline int audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) { if (unlikely(!audit_dummy_context())) - __audit_mq_getsetattr(mqdes, mqstat); + return __audit_mq_getsetattr(mqdes, mqstat); + return 0; } static inline int audit_log_bprm_fcaps(struct linux_binprm *bprm, @@ -518,11 +518,12 @@ static inline int audit_log_bprm_fcaps(struct linux_binprm *bprm, return 0; } -static inline void audit_log_capset(pid_t pid, const struct cred *new, +static inline int audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old) { if (unlikely(!audit_dummy_context())) - __audit_log_capset(pid, new, old); + return __audit_log_capset(pid, new, old); + return 0; } extern int audit_n_rules; @@ -545,19 +546,20 @@ extern int audit_signals; #define audit_get_loginuid(t) (-1) #define audit_get_sessionid(t) (-1) #define audit_log_task_context(b) do { ; } while (0) -#define audit_ipc_obj(i) ((void)0) -#define audit_ipc_set_perm(q,u,g,m) ((void)0) +#define audit_ipc_obj(i) ({ 0; }) +#define audit_ipc_set_perm(q,u,g,m) ({ 0; }) #define audit_bprm(p) ({ 0; }) -#define audit_socketcall(n,a) ((void)0) -#define audit_fd_pair(n,a) ((void)0) +#define audit_socketcall(n,a) ({ 0; }) +#define audit_fd_pair(n,a) ({ 0; }) #define audit_sockaddr(len, addr) ({ 0; }) #define audit_set_macxattr(n) do { ; } while (0) -#define audit_mq_open(o,m,a) ((void)0) -#define audit_mq_sendrecv(d,l,p,t) ((void)0) -#define audit_mq_notify(d,n) ((void)0) -#define audit_mq_getsetattr(d,s) ((void)0) +#define audit_mq_open(o,m,a) ({ 0; }) +#define audit_mq_timedsend(d,l,p,t) ({ 0; }) +#define audit_mq_timedreceive(d,l,p,t) ({ 0; }) +#define audit_mq_notify(d,n) ({ 0; }) +#define audit_mq_getsetattr(d,s) ({ 0; }) #define audit_log_bprm_fcaps(b, ncr, ocr) ({ 0; }) -#define audit_log_capset(pid, ncr, ocr) ((void)0) +#define audit_log_capset(pid, ncr, ocr) ({ 0; }) #define audit_ptrace(t) ((void)0) #define audit_n_rules 0 #define audit_signals 0 diff --git a/trunk/include/linux/blockgroup_lock.h b/trunk/include/linux/blockgroup_lock.h index e44b88ba552b..8607312983bd 100644 --- a/trunk/include/linux/blockgroup_lock.h +++ b/trunk/include/linux/blockgroup_lock.h @@ -53,10 +53,7 @@ static inline void bgl_lock_init(struct blockgroup_lock *bgl) * The accessor is a macro so we can embed a blockgroup_lock into different * superblock types */ -static inline spinlock_t * -bgl_lock_ptr(struct blockgroup_lock *bgl, unsigned int block_group) -{ - return &bgl->locks[(block_group) & (NR_BG_LOCKS-1)].lock; -} +#define sb_bgl_lock(sb, block_group) \ + (&(sb)->s_blockgroup_lock.locks[(block_group) & (NR_BG_LOCKS-1)].lock) #endif diff --git a/trunk/include/linux/ext2_fs_sb.h b/trunk/include/linux/ext2_fs_sb.h index dc541f3653d1..f273415ab6f1 100644 --- a/trunk/include/linux/ext2_fs_sb.h +++ b/trunk/include/linux/ext2_fs_sb.h @@ -108,10 +108,4 @@ struct ext2_sb_info { struct ext2_reserve_window_node s_rsv_window_head; }; -static inline spinlock_t * -sb_bgl_lock(struct ext2_sb_info *sbi, unsigned int block_group) -{ - return bgl_lock_ptr(&sbi->s_blockgroup_lock, block_group); -} - #endif /* _LINUX_EXT2_FS_SB */ diff --git a/trunk/include/linux/ext3_fs_sb.h b/trunk/include/linux/ext3_fs_sb.h index e024e38248ff..b65f0288b842 100644 --- a/trunk/include/linux/ext3_fs_sb.h +++ b/trunk/include/linux/ext3_fs_sb.h @@ -83,10 +83,4 @@ struct ext3_sb_info { #endif }; -static inline spinlock_t * -sb_bgl_lock(struct ext3_sb_info *sbi, unsigned int block_group) -{ - return bgl_lock_ptr(&sbi->s_blockgroup_lock, block_group); -} - #endif /* _LINUX_EXT3_FS_SB */ diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index f2a3010140e3..e2170ee21e18 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -423,9 +423,6 @@ enum positive_aop_returns { #define AOP_FLAG_UNINTERRUPTIBLE 0x0001 /* will not do a short write */ #define AOP_FLAG_CONT_EXPAND 0x0002 /* called from cont_expand */ -#define AOP_FLAG_NOFS 0x0004 /* used by filesystem to direct - * helper code (eg buffer layer) - * to clear GFP_FS from alloc */ /* * oh the beauties of C type declarations. @@ -2038,7 +2035,7 @@ extern int page_readlink(struct dentry *, char __user *, int); extern void *page_follow_link_light(struct dentry *, struct nameidata *); extern void page_put_link(struct dentry *, struct nameidata *, void *); extern int __page_symlink(struct inode *inode, const char *symname, int len, - int nofs); + gfp_t gfp_mask); extern int page_symlink(struct inode *inode, const char *symname, int len); extern const struct inode_operations page_symlink_inode_operations; extern int generic_readlink(struct dentry *, char __user *, int); diff --git a/trunk/include/linux/pagemap.h b/trunk/include/linux/pagemap.h index 01ca0856caff..709742be02f0 100644 --- a/trunk/include/linux/pagemap.h +++ b/trunk/include/linux/pagemap.h @@ -241,8 +241,7 @@ unsigned find_get_pages_contig(struct address_space *mapping, pgoff_t start, unsigned find_get_pages_tag(struct address_space *mapping, pgoff_t *index, int tag, unsigned int nr_pages, struct page **pages); -struct page *grab_cache_page_write_begin(struct address_space *mapping, - pgoff_t index, unsigned flags); +struct page *__grab_cache_page(struct address_space *mapping, pgoff_t index); /* * Returns locked page at given index in given cache, creating it if needed. diff --git a/trunk/include/linux/radix-tree.h b/trunk/include/linux/radix-tree.h index 355f6e80db0d..a916c6660dfa 100644 --- a/trunk/include/linux/radix-tree.h +++ b/trunk/include/linux/radix-tree.h @@ -136,7 +136,7 @@ do { \ */ static inline void *radix_tree_deref_slot(void **pslot) { - void *ret = rcu_dereference(*pslot); + void *ret = *pslot; if (unlikely(radix_tree_is_indirect_ptr(ret))) ret = RADIX_TREE_RETRY; return ret; diff --git a/trunk/include/linux/rtc.h b/trunk/include/linux/rtc.h index 4046b75563c1..91f597ad6acc 100644 --- a/trunk/include/linux/rtc.h +++ b/trunk/include/linux/rtc.h @@ -145,8 +145,6 @@ struct rtc_class_ops { int (*irq_set_state)(struct device *, int enabled); int (*irq_set_freq)(struct device *, int freq); int (*read_callback)(struct device *, int data); - int (*alarm_irq_enable)(struct device *, unsigned int enabled); - int (*update_irq_enable)(struct device *, unsigned int enabled); }; #define RTC_DEVICE_NAME_SIZE 20 @@ -183,7 +181,7 @@ struct rtc_device struct timer_list uie_timer; /* Those fields are protected by rtc->irq_lock */ unsigned int oldsecs; - unsigned int uie_irq_active:1; + unsigned int irq_active:1; unsigned int stop_uie_polling:1; unsigned int uie_task_active:1; unsigned int uie_timer_active:1; @@ -218,10 +216,6 @@ extern int rtc_irq_set_state(struct rtc_device *rtc, struct rtc_task *task, int enabled); extern int rtc_irq_set_freq(struct rtc_device *rtc, struct rtc_task *task, int freq); -extern int rtc_update_irq_enable(struct rtc_device *rtc, unsigned int enabled); -extern int rtc_alarm_irq_enable(struct rtc_device *rtc, unsigned int enabled); -extern int rtc_dev_update_irq_enable_emul(struct rtc_device *rtc, - unsigned int enabled); typedef struct rtc_task { void (*func)(void *private_data); diff --git a/trunk/include/linux/spi/spi.h b/trunk/include/linux/spi/spi.h index 82229317753d..4be01bb44377 100644 --- a/trunk/include/linux/spi/spi.h +++ b/trunk/include/linux/spi/spi.h @@ -19,8 +19,6 @@ #ifndef __LINUX_SPI_H #define __LINUX_SPI_H -#include - /* * INTERFACES between SPI master-side drivers and SPI infrastructure. * (There's no SPI slave support for Linux yet...) diff --git a/trunk/ipc/mqueue.c b/trunk/ipc/mqueue.c index d448b69672b5..d9393f8e4c3e 100644 --- a/trunk/ipc/mqueue.c +++ b/trunk/ipc/mqueue.c @@ -524,27 +524,31 @@ static void __do_notify(struct mqueue_inode_info *info) wake_up(&info->wait_q); } -static long prepare_timeout(struct timespec *p) +static long prepare_timeout(const struct timespec __user *u_arg) { - struct timespec nowts; + struct timespec ts, nowts; long timeout; - if (p) { - if (unlikely(p->tv_nsec < 0 || p->tv_sec < 0 - || p->tv_nsec >= NSEC_PER_SEC)) + if (u_arg) { + if (unlikely(copy_from_user(&ts, u_arg, + sizeof(struct timespec)))) + return -EFAULT; + + if (unlikely(ts.tv_nsec < 0 || ts.tv_sec < 0 + || ts.tv_nsec >= NSEC_PER_SEC)) return -EINVAL; nowts = CURRENT_TIME; /* first subtract as jiffies can't be too big */ - p->tv_sec -= nowts.tv_sec; - if (p->tv_nsec < nowts.tv_nsec) { - p->tv_nsec += NSEC_PER_SEC; - p->tv_sec--; + ts.tv_sec -= nowts.tv_sec; + if (ts.tv_nsec < nowts.tv_nsec) { + ts.tv_nsec += NSEC_PER_SEC; + ts.tv_sec--; } - p->tv_nsec -= nowts.tv_nsec; - if (p->tv_sec < 0) + ts.tv_nsec -= nowts.tv_nsec; + if (ts.tv_sec < 0) return 0; - timeout = timespec_to_jiffies(p) + 1; + timeout = timespec_to_jiffies(&ts) + 1; } else return MAX_SCHEDULE_TIMEOUT; @@ -588,18 +592,22 @@ static int mq_attr_ok(struct mq_attr *attr) * Invoked when creating a new queue via sys_mq_open */ static struct file *do_create(struct dentry *dir, struct dentry *dentry, - int oflag, mode_t mode, struct mq_attr *attr) + int oflag, mode_t mode, struct mq_attr __user *u_attr) { const struct cred *cred = current_cred(); + struct mq_attr attr; struct file *result; int ret; - if (attr) { + if (u_attr) { + ret = -EFAULT; + if (copy_from_user(&attr, u_attr, sizeof(attr))) + goto out; ret = -EINVAL; - if (!mq_attr_ok(attr)) + if (!mq_attr_ok(&attr)) goto out; /* store for use during create */ - dentry->d_fsdata = attr; + dentry->d_fsdata = &attr; } mode &= ~current->fs->umask; @@ -656,13 +664,11 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, struct dentry *dentry; struct file *filp; char *name; - struct mq_attr attr; int fd, error; - if (u_attr && copy_from_user(&attr, u_attr, sizeof(struct mq_attr))) - return -EFAULT; - - audit_mq_open(oflag, mode, u_attr ? &attr : NULL); + error = audit_mq_open(oflag, mode, u_attr); + if (error != 0) + return error; if (IS_ERR(name = getname(u_name))) return PTR_ERR(name); @@ -688,8 +694,7 @@ asmlinkage long sys_mq_open(const char __user *u_name, int oflag, mode_t mode, filp = do_open(dentry, oflag); } else { filp = do_create(mqueue_mnt->mnt_root, dentry, - oflag, mode, - u_attr ? &attr : NULL); + oflag, mode, u_attr); } } else { error = -ENOENT; @@ -824,22 +829,17 @@ asmlinkage long sys_mq_timedsend(mqd_t mqdes, const char __user *u_msg_ptr, struct ext_wait_queue *receiver; struct msg_msg *msg_ptr; struct mqueue_inode_info *info; - struct timespec ts, *p = NULL; long timeout; int ret; - if (u_abs_timeout) { - if (copy_from_user(&ts, u_abs_timeout, - sizeof(struct timespec))) - return -EFAULT; - p = &ts; - } + ret = audit_mq_timedsend(mqdes, msg_len, msg_prio, u_abs_timeout); + if (ret != 0) + return ret; if (unlikely(msg_prio >= (unsigned long) MQ_PRIO_MAX)) return -EINVAL; - audit_mq_sendrecv(mqdes, msg_len, msg_prio, p); - timeout = prepare_timeout(p); + timeout = prepare_timeout(u_abs_timeout); ret = -EBADF; filp = fget(mqdes); @@ -918,17 +918,12 @@ asmlinkage ssize_t sys_mq_timedreceive(mqd_t mqdes, char __user *u_msg_ptr, struct inode *inode; struct mqueue_inode_info *info; struct ext_wait_queue wait; - struct timespec ts, *p = NULL; - if (u_abs_timeout) { - if (copy_from_user(&ts, u_abs_timeout, - sizeof(struct timespec))) - return -EFAULT; - p = &ts; - } + ret = audit_mq_timedreceive(mqdes, msg_len, u_msg_prio, u_abs_timeout); + if (ret != 0) + return ret; - audit_mq_sendrecv(mqdes, msg_len, 0, p); - timeout = prepare_timeout(p); + timeout = prepare_timeout(u_abs_timeout); ret = -EBADF; filp = fget(mqdes); @@ -1008,17 +1003,17 @@ asmlinkage long sys_mq_notify(mqd_t mqdes, struct mqueue_inode_info *info; struct sk_buff *nc; - if (u_notification) { - if (copy_from_user(¬ification, u_notification, - sizeof(struct sigevent))) - return -EFAULT; - } - - audit_mq_notify(mqdes, u_notification ? ¬ification : NULL); + ret = audit_mq_notify(mqdes, u_notification); + if (ret != 0) + return ret; nc = NULL; sock = NULL; if (u_notification != NULL) { + if (copy_from_user(¬ification, u_notification, + sizeof(struct sigevent))) + return -EFAULT; + if (unlikely(notification.sigev_notify != SIGEV_NONE && notification.sigev_notify != SIGEV_SIGNAL && notification.sigev_notify != SIGEV_THREAD)) @@ -1155,7 +1150,11 @@ asmlinkage long sys_mq_getsetattr(mqd_t mqdes, omqstat = info->attr; omqstat.mq_flags = filp->f_flags & O_NONBLOCK; if (u_mqstat) { - audit_mq_getsetattr(mqdes, &mqstat); + ret = audit_mq_getsetattr(mqdes, &mqstat); + if (ret != 0) { + spin_unlock(&info->lock); + goto out_fput; + } if (mqstat.mq_flags & O_NONBLOCK) filp->f_flags |= O_NONBLOCK; else diff --git a/trunk/ipc/sem.c b/trunk/ipc/sem.c index fea0ad3aed7b..082122469b17 100644 --- a/trunk/ipc/sem.c +++ b/trunk/ipc/sem.c @@ -58,7 +58,7 @@ * SMP-threaded, sysctl's added * (c) 1999 Manfred Spraul * Enforced range limit on SEM_UNDO - * (c) 2001 Red Hat Inc + * (c) 2001 Red Hat Inc * Lockless wakeup * (c) 2003 Manfred Spraul * diff --git a/trunk/ipc/shm.c b/trunk/ipc/shm.c index 57dd50046cef..38a055758a9b 100644 --- a/trunk/ipc/shm.c +++ b/trunk/ipc/shm.c @@ -747,7 +747,9 @@ asmlinkage long sys_shmctl(int shmid, int cmd, struct shmid_ds __user *buf) goto out; } - audit_ipc_obj(&(shp->shm_perm)); + err = audit_ipc_obj(&(shp->shm_perm)); + if (err) + goto out_unlock; if (!capable(CAP_IPC_LOCK)) { uid_t euid = current_euid(); diff --git a/trunk/ipc/util.c b/trunk/ipc/util.c index 7585a72e259b..5a1808c774a2 100644 --- a/trunk/ipc/util.c +++ b/trunk/ipc/util.c @@ -624,9 +624,10 @@ void ipc_rcu_putref(void *ptr) int ipcperms (struct kern_ipc_perm *ipcp, short flag) { /* flag will most probably be 0 or S_...UGO from */ uid_t euid = current_euid(); - int requested_mode, granted_mode; + int requested_mode, granted_mode, err; - audit_ipc_obj(ipcp); + if (unlikely((err = audit_ipc_obj(ipcp)))) + return err; requested_mode = (flag >> 6) | (flag >> 3) | flag; granted_mode = ipcp->mode; if (euid == ipcp->cuid || @@ -802,10 +803,16 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, goto out_up; } - audit_ipc_obj(ipcp); - if (cmd == IPC_SET) - audit_ipc_set_perm(extra_perm, perm->uid, + err = audit_ipc_obj(ipcp); + if (err) + goto out_unlock; + + if (cmd == IPC_SET) { + err = audit_ipc_set_perm(extra_perm, perm->uid, perm->gid, perm->mode); + if (err) + goto out_unlock; + } euid = current_euid(); if (euid == ipcp->cuid || @@ -813,6 +820,7 @@ struct kern_ipc_perm *ipcctl_pre_down(struct ipc_ids *ids, int id, int cmd, return ipcp; err = -EPERM; +out_unlock: ipc_unlock(ipcp); out_up: up_write(&ids->rw_mutex); diff --git a/trunk/kernel/audit.h b/trunk/kernel/audit.h index 16f18cac661b..9d6717412fec 100644 --- a/trunk/kernel/audit.h +++ b/trunk/kernel/audit.h @@ -159,8 +159,11 @@ static inline int audit_signal_info(int sig, struct task_struct *t) return __audit_signal_info(sig, t); return 0; } -extern void audit_filter_inodes(struct task_struct *, struct audit_context *); +extern enum audit_state audit_filter_inodes(struct task_struct *, + struct audit_context *); +extern void audit_set_auditable(struct audit_context *); #else #define audit_signal_info(s,t) AUDIT_DISABLED #define audit_filter_inodes(t,c) AUDIT_DISABLED +#define audit_set_auditable(c) #endif diff --git a/trunk/kernel/audit_tree.c b/trunk/kernel/audit_tree.c index 8ad9545b8db9..8b509441f49a 100644 --- a/trunk/kernel/audit_tree.c +++ b/trunk/kernel/audit_tree.c @@ -450,7 +450,6 @@ static void kill_rules(struct audit_tree *tree) audit_log_end(ab); rule->tree = NULL; list_del_rcu(&entry->list); - list_del(&entry->rule.list); call_rcu(&entry->rcu, audit_free_rule_rcu); } } @@ -618,7 +617,7 @@ int audit_make_tree(struct audit_krule *rule, char *pathname, u32 op) if (pathname[0] != '/' || rule->listnr != AUDIT_FILTER_EXIT || - op != Audit_equal || + op & ~AUDIT_EQUAL || rule->inode_f || rule->watch || rule->tree) return -EINVAL; rule->tree = alloc_tree(pathname); diff --git a/trunk/kernel/auditfilter.c b/trunk/kernel/auditfilter.c index fbf24d121d97..9fd85a4640a0 100644 --- a/trunk/kernel/auditfilter.c +++ b/trunk/kernel/auditfilter.c @@ -86,14 +86,6 @@ struct list_head audit_filter_list[AUDIT_NR_FILTERS] = { #error Fix audit_filter_list initialiser #endif }; -static struct list_head audit_rules_list[AUDIT_NR_FILTERS] = { - LIST_HEAD_INIT(audit_rules_list[0]), - LIST_HEAD_INIT(audit_rules_list[1]), - LIST_HEAD_INIT(audit_rules_list[2]), - LIST_HEAD_INIT(audit_rules_list[3]), - LIST_HEAD_INIT(audit_rules_list[4]), - LIST_HEAD_INIT(audit_rules_list[5]), -}; DEFINE_MUTEX(audit_filter_mutex); @@ -252,8 +244,7 @@ static inline int audit_to_inode(struct audit_krule *krule, struct audit_field *f) { if (krule->listnr != AUDIT_FILTER_EXIT || - krule->watch || krule->inode_f || krule->tree || - (f->op != Audit_equal && f->op != Audit_not_equal)) + krule->watch || krule->inode_f || krule->tree) return -EINVAL; krule->inode_f = f; @@ -271,7 +262,7 @@ static int audit_to_watch(struct audit_krule *krule, char *path, int len, if (path[0] != '/' || path[len-1] == '/' || krule->listnr != AUDIT_FILTER_EXIT || - op != Audit_equal || + op & ~AUDIT_EQUAL || krule->inode_f || krule->watch || krule->tree) return -EINVAL; @@ -421,32 +412,12 @@ static inline struct audit_entry *audit_to_entry_common(struct audit_rule *rule) return ERR_PTR(err); } -static u32 audit_ops[] = -{ - [Audit_equal] = AUDIT_EQUAL, - [Audit_not_equal] = AUDIT_NOT_EQUAL, - [Audit_bitmask] = AUDIT_BIT_MASK, - [Audit_bittest] = AUDIT_BIT_TEST, - [Audit_lt] = AUDIT_LESS_THAN, - [Audit_gt] = AUDIT_GREATER_THAN, - [Audit_le] = AUDIT_LESS_THAN_OR_EQUAL, - [Audit_ge] = AUDIT_GREATER_THAN_OR_EQUAL, -}; - -static u32 audit_to_op(u32 op) -{ - u32 n; - for (n = Audit_equal; n < Audit_bad && audit_ops[n] != op; n++) - ; - return n; -} - - /* Translate struct audit_rule to kernel's rule respresentation. * Exists for backward compatibility with userspace. */ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) { struct audit_entry *entry; + struct audit_field *ino_f; int err = 0; int i; @@ -456,28 +427,12 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) for (i = 0; i < rule->field_count; i++) { struct audit_field *f = &entry->rule.fields[i]; - u32 n; - - n = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS); - - /* Support for legacy operators where - * AUDIT_NEGATE bit signifies != and otherwise assumes == */ - if (n & AUDIT_NEGATE) - f->op = Audit_not_equal; - else if (!n) - f->op = Audit_equal; - else - f->op = audit_to_op(n); - - entry->rule.vers_ops = (n & AUDIT_OPERATORS) ? 2 : 1; + f->op = rule->fields[i] & (AUDIT_NEGATE|AUDIT_OPERATORS); f->type = rule->fields[i] & ~(AUDIT_NEGATE|AUDIT_OPERATORS); f->val = rule->values[i]; err = -EINVAL; - if (f->op == Audit_bad) - goto exit_free; - switch(f->type) { default: goto exit_free; @@ -499,8 +454,11 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) case AUDIT_EXIT: case AUDIT_SUCCESS: /* bit ops are only useful on syscall args */ - if (f->op == Audit_bitmask || f->op == Audit_bittest) + if (f->op == AUDIT_BIT_MASK || + f->op == AUDIT_BIT_TEST) { + err = -EINVAL; goto exit_free; + } break; case AUDIT_ARG0: case AUDIT_ARG1: @@ -509,8 +467,11 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) break; /* arch is only allowed to be = or != */ case AUDIT_ARCH: - if (f->op != Audit_not_equal && f->op != Audit_equal) + if ((f->op != AUDIT_NOT_EQUAL) && (f->op != AUDIT_EQUAL) + && (f->op != AUDIT_NEGATE) && (f->op)) { + err = -EINVAL; goto exit_free; + } entry->rule.arch_f = f; break; case AUDIT_PERM: @@ -527,10 +488,33 @@ static struct audit_entry *audit_rule_to_entry(struct audit_rule *rule) goto exit_free; break; } + + entry->rule.vers_ops = (f->op & AUDIT_OPERATORS) ? 2 : 1; + + /* Support for legacy operators where + * AUDIT_NEGATE bit signifies != and otherwise assumes == */ + if (f->op & AUDIT_NEGATE) + f->op = AUDIT_NOT_EQUAL; + else if (!f->op) + f->op = AUDIT_EQUAL; + else if (f->op == AUDIT_OPERATORS) { + err = -EINVAL; + goto exit_free; + } } - if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal) - entry->rule.inode_f = NULL; + ino_f = entry->rule.inode_f; + if (ino_f) { + switch(ino_f->op) { + case AUDIT_NOT_EQUAL: + entry->rule.inode_f = NULL; + case AUDIT_EQUAL: + break; + default: + err = -EINVAL; + goto exit_free; + } + } exit_nofree: return entry; @@ -546,6 +530,7 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, { int err = 0; struct audit_entry *entry; + struct audit_field *ino_f; void *bufp; size_t remain = datasz - sizeof(struct audit_rule_data); int i; @@ -561,11 +546,11 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, struct audit_field *f = &entry->rule.fields[i]; err = -EINVAL; - - f->op = audit_to_op(data->fieldflags[i]); - if (f->op == Audit_bad) + if (!(data->fieldflags[i] & AUDIT_OPERATORS) || + data->fieldflags[i] & ~AUDIT_OPERATORS) goto exit_free; + f->op = data->fieldflags[i] & AUDIT_OPERATORS; f->type = data->fields[i]; f->val = data->values[i]; f->lsm_str = NULL; @@ -677,8 +662,18 @@ static struct audit_entry *audit_data_to_entry(struct audit_rule_data *data, } } - if (entry->rule.inode_f && entry->rule.inode_f->op == Audit_not_equal) - entry->rule.inode_f = NULL; + ino_f = entry->rule.inode_f; + if (ino_f) { + switch(ino_f->op) { + case AUDIT_NOT_EQUAL: + entry->rule.inode_f = NULL; + case AUDIT_EQUAL: + break; + default: + err = -EINVAL; + goto exit_free; + } + } exit_nofree: return entry; @@ -718,10 +713,10 @@ static struct audit_rule *audit_krule_to_rule(struct audit_krule *krule) rule->fields[i] = krule->fields[i].type; if (krule->vers_ops == 1) { - if (krule->fields[i].op == Audit_not_equal) + if (krule->fields[i].op & AUDIT_NOT_EQUAL) rule->fields[i] |= AUDIT_NEGATE; } else { - rule->fields[i] |= audit_ops[krule->fields[i].op]; + rule->fields[i] |= krule->fields[i].op; } } for (i = 0; i < AUDIT_BITMASK_SIZE; i++) rule->mask[i] = krule->mask[i]; @@ -749,7 +744,7 @@ static struct audit_rule_data *audit_krule_to_data(struct audit_krule *krule) struct audit_field *f = &krule->fields[i]; data->fields[i] = f->type; - data->fieldflags[i] = audit_ops[f->op]; + data->fieldflags[i] = f->op; switch(f->type) { case AUDIT_SUBJ_USER: case AUDIT_SUBJ_ROLE: @@ -924,7 +919,6 @@ static struct audit_entry *audit_dupe_rule(struct audit_krule *old, new->action = old->action; for (i = 0; i < AUDIT_BITMASK_SIZE; i++) new->mask[i] = old->mask[i]; - new->prio = old->prio; new->buflen = old->buflen; new->inode_f = old->inode_f; new->watch = NULL; @@ -993,8 +987,9 @@ static void audit_update_watch(struct audit_parent *parent, /* If the update involves invalidating rules, do the inode-based * filtering now, so we don't omit records. */ - if (invalidating && current->audit_context) - audit_filter_inodes(current, current->audit_context); + if (invalidating && current->audit_context && + audit_filter_inodes(current, current->audit_context) == AUDIT_RECORD_CONTEXT) + audit_set_auditable(current->audit_context); nwatch = audit_dupe_watch(owatch); if (IS_ERR(nwatch)) { @@ -1012,15 +1007,12 @@ static void audit_update_watch(struct audit_parent *parent, list_del_rcu(&oentry->list); nentry = audit_dupe_rule(&oentry->rule, nwatch); - if (IS_ERR(nentry)) { - list_del(&oentry->rule.list); + if (IS_ERR(nentry)) audit_panic("error updating watch, removing"); - } else { + else { int h = audit_hash_ino((u32)ino); list_add(&nentry->rule.rlist, &nwatch->rules); list_add_rcu(&nentry->list, &audit_inode_hash[h]); - list_replace(&oentry->rule.list, - &nentry->rule.list); } call_rcu(&oentry->rcu, audit_free_rule_rcu); @@ -1085,7 +1077,6 @@ static void audit_remove_parent_watches(struct audit_parent *parent) audit_log_end(ab); } list_del(&r->rlist); - list_del(&r->list); list_del_rcu(&e->list); call_rcu(&e->rcu, audit_free_rule_rcu); } @@ -1111,16 +1102,12 @@ static void audit_inotify_unregister(struct list_head *in_list) /* Find an existing audit rule. * Caller must hold audit_filter_mutex to prevent stale rule data. */ static struct audit_entry *audit_find_rule(struct audit_entry *entry, - struct list_head **p) + struct list_head *list) { struct audit_entry *e, *found = NULL; - struct list_head *list; int h; - if (entry->rule.inode_f) { - h = audit_hash_ino(entry->rule.inode_f->val); - *p = list = &audit_inode_hash[h]; - } else if (entry->rule.watch) { + if (entry->rule.watch) { /* we don't know the inode number, so must walk entire hash */ for (h = 0; h < AUDIT_INODE_BUCKETS; h++) { list = &audit_inode_hash[h]; @@ -1131,8 +1118,6 @@ static struct audit_entry *audit_find_rule(struct audit_entry *entry, } } goto out; - } else { - *p = list = &audit_filter_list[entry->rule.listnr]; } list_for_each_entry(e, list, list) @@ -1273,17 +1258,15 @@ static int audit_add_watch(struct audit_krule *krule, struct nameidata *ndp, return ret; } -static u64 prio_low = ~0ULL/2; -static u64 prio_high = ~0ULL/2 - 1; - /* Add rule to given filterlist if not a duplicate. */ -static inline int audit_add_rule(struct audit_entry *entry) +static inline int audit_add_rule(struct audit_entry *entry, + struct list_head *list) { struct audit_entry *e; + struct audit_field *inode_f = entry->rule.inode_f; struct audit_watch *watch = entry->rule.watch; struct audit_tree *tree = entry->rule.tree; struct nameidata *ndp = NULL, *ndw = NULL; - struct list_head *list; int h, err; #ifdef CONFIG_AUDITSYSCALL int dont_count = 0; @@ -1294,8 +1277,13 @@ static inline int audit_add_rule(struct audit_entry *entry) dont_count = 1; #endif + if (inode_f) { + h = audit_hash_ino(inode_f->val); + list = &audit_inode_hash[h]; + } + mutex_lock(&audit_filter_mutex); - e = audit_find_rule(entry, &list); + e = audit_find_rule(entry, list); mutex_unlock(&audit_filter_mutex); if (e) { err = -EEXIST; @@ -1331,22 +1319,10 @@ static inline int audit_add_rule(struct audit_entry *entry) } } - entry->rule.prio = ~0ULL; - if (entry->rule.listnr == AUDIT_FILTER_EXIT) { - if (entry->rule.flags & AUDIT_FILTER_PREPEND) - entry->rule.prio = ++prio_high; - else - entry->rule.prio = --prio_low; - } - if (entry->rule.flags & AUDIT_FILTER_PREPEND) { - list_add(&entry->rule.list, - &audit_rules_list[entry->rule.listnr]); list_add_rcu(&entry->list, list); entry->rule.flags &= ~AUDIT_FILTER_PREPEND; } else { - list_add_tail(&entry->rule.list, - &audit_rules_list[entry->rule.listnr]); list_add_tail_rcu(&entry->list, list); } #ifdef CONFIG_AUDITSYSCALL @@ -1369,14 +1345,15 @@ static inline int audit_add_rule(struct audit_entry *entry) } /* Remove an existing rule from filterlist. */ -static inline int audit_del_rule(struct audit_entry *entry) +static inline int audit_del_rule(struct audit_entry *entry, + struct list_head *list) { struct audit_entry *e; + struct audit_field *inode_f = entry->rule.inode_f; struct audit_watch *watch, *tmp_watch = entry->rule.watch; struct audit_tree *tree = entry->rule.tree; - struct list_head *list; LIST_HEAD(inotify_list); - int ret = 0; + int h, ret = 0; #ifdef CONFIG_AUDITSYSCALL int dont_count = 0; @@ -1386,8 +1363,13 @@ static inline int audit_del_rule(struct audit_entry *entry) dont_count = 1; #endif + if (inode_f) { + h = audit_hash_ino(inode_f->val); + list = &audit_inode_hash[h]; + } + mutex_lock(&audit_filter_mutex); - e = audit_find_rule(entry, &list); + e = audit_find_rule(entry, list); if (!e) { mutex_unlock(&audit_filter_mutex); ret = -ENOENT; @@ -1422,7 +1404,6 @@ static inline int audit_del_rule(struct audit_entry *entry) audit_remove_tree_rule(&e->rule); list_del_rcu(&e->list); - list_del(&e->rule.list); call_rcu(&e->rcu, audit_free_rule_rcu); #ifdef CONFIG_AUDITSYSCALL @@ -1451,16 +1432,30 @@ static inline int audit_del_rule(struct audit_entry *entry) static void audit_list(int pid, int seq, struct sk_buff_head *q) { struct sk_buff *skb; - struct audit_krule *r; + struct audit_entry *entry; int i; /* This is a blocking read, so use audit_filter_mutex instead of rcu * iterator to sync with list writers. */ for (i=0; irule); + if (unlikely(!rule)) + break; + skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1, + rule, sizeof(*rule)); + if (skb) + skb_queue_tail(q, skb); + kfree(rule); + } + } + for (i = 0; i < AUDIT_INODE_BUCKETS; i++) { + list_for_each_entry(entry, &audit_inode_hash[i], list) { struct audit_rule *rule; - rule = audit_krule_to_rule(r); + rule = audit_krule_to_rule(&entry->rule); if (unlikely(!rule)) break; skb = audit_make_reply(pid, seq, AUDIT_LIST, 0, 1, @@ -1479,16 +1474,30 @@ static void audit_list(int pid, int seq, struct sk_buff_head *q) static void audit_list_rules(int pid, int seq, struct sk_buff_head *q) { struct sk_buff *skb; - struct audit_krule *r; + struct audit_entry *e; int i; /* This is a blocking read, so use audit_filter_mutex instead of rcu * iterator to sync with list writers. */ for (i=0; irule); + if (unlikely(!data)) + break; + skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1, + data, sizeof(*data) + data->buflen); + if (skb) + skb_queue_tail(q, skb); + kfree(data); + } + } + for (i=0; i< AUDIT_INODE_BUCKETS; i++) { + list_for_each_entry(e, &audit_inode_hash[i], list) { struct audit_rule_data *data; - data = audit_krule_to_data(r); + data = audit_krule_to_data(&e->rule); if (unlikely(!data)) break; skb = audit_make_reply(pid, seq, AUDIT_LIST_RULES, 0, 1, @@ -1594,7 +1603,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, if (IS_ERR(entry)) return PTR_ERR(entry); - err = audit_add_rule(entry); + err = audit_add_rule(entry, + &audit_filter_list[entry->rule.listnr]); audit_log_rule_change(loginuid, sessionid, sid, "add", &entry->rule, !err); @@ -1610,7 +1620,8 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, if (IS_ERR(entry)) return PTR_ERR(entry); - err = audit_del_rule(entry); + err = audit_del_rule(entry, + &audit_filter_list[entry->rule.listnr]); audit_log_rule_change(loginuid, sessionid, sid, "remove", &entry->rule, !err); @@ -1623,29 +1634,28 @@ int audit_receive_filter(int type, int pid, int uid, int seq, void *data, return err; } -int audit_comparator(u32 left, u32 op, u32 right) +int audit_comparator(const u32 left, const u32 op, const u32 right) { switch (op) { - case Audit_equal: + case AUDIT_EQUAL: return (left == right); - case Audit_not_equal: + case AUDIT_NOT_EQUAL: return (left != right); - case Audit_lt: + case AUDIT_LESS_THAN: return (left < right); - case Audit_le: + case AUDIT_LESS_THAN_OR_EQUAL: return (left <= right); - case Audit_gt: + case AUDIT_GREATER_THAN: return (left > right); - case Audit_ge: + case AUDIT_GREATER_THAN_OR_EQUAL: return (left >= right); - case Audit_bitmask: + case AUDIT_BIT_MASK: return (left & right); - case Audit_bittest: + case AUDIT_BIT_TEST: return ((left & right) == right); - default: - BUG(); - return 0; } + BUG(); + return 0; } /* Compare given dentry name with last component in given path, @@ -1768,43 +1778,6 @@ int audit_filter_type(int type) return result; } -static int update_lsm_rule(struct audit_krule *r) -{ - struct audit_entry *entry = container_of(r, struct audit_entry, rule); - struct audit_entry *nentry; - struct audit_watch *watch; - struct audit_tree *tree; - int err = 0; - - if (!security_audit_rule_known(r)) - return 0; - - watch = r->watch; - tree = r->tree; - nentry = audit_dupe_rule(r, watch); - if (IS_ERR(nentry)) { - /* save the first error encountered for the - * return value */ - err = PTR_ERR(nentry); - audit_panic("error updating LSM filters"); - if (watch) - list_del(&r->rlist); - list_del_rcu(&entry->list); - list_del(&r->list); - } else { - if (watch) { - list_add(&nentry->rule.rlist, &watch->rules); - list_del(&r->rlist); - } else if (tree) - list_replace_init(&r->rlist, &nentry->rule.rlist); - list_replace_rcu(&entry->list, &nentry->list); - list_replace(&r->list, &nentry->rule.list); - } - call_rcu(&entry->rcu, audit_free_rule_rcu); - - return err; -} - /* This function will re-initialize the lsm_rule field of all applicable rules. * It will traverse the filter lists serarching for rules that contain LSM * specific filter fields. When such a rule is found, it is copied, the @@ -1812,19 +1785,45 @@ static int update_lsm_rule(struct audit_krule *r) * updated rule. */ int audit_update_lsm_rules(void) { - struct audit_krule *r, *n; + struct audit_entry *entry, *n, *nentry; + struct audit_watch *watch; + struct audit_tree *tree; int i, err = 0; /* audit_filter_mutex synchronizes the writers */ mutex_lock(&audit_filter_mutex); for (i = 0; i < AUDIT_NR_FILTERS; i++) { - list_for_each_entry_safe(r, n, &audit_rules_list[i], list) { - int res = update_lsm_rule(r); - if (!err) - err = res; + list_for_each_entry_safe(entry, n, &audit_filter_list[i], list) { + if (!security_audit_rule_known(&entry->rule)) + continue; + + watch = entry->rule.watch; + tree = entry->rule.tree; + nentry = audit_dupe_rule(&entry->rule, watch); + if (IS_ERR(nentry)) { + /* save the first error encountered for the + * return value */ + if (!err) + err = PTR_ERR(nentry); + audit_panic("error updating LSM filters"); + if (watch) + list_del(&entry->rule.rlist); + list_del_rcu(&entry->list); + } else { + if (watch) { + list_add(&nentry->rule.rlist, + &watch->rules); + list_del(&entry->rule.rlist); + } else if (tree) + list_replace_init(&entry->rule.rlist, + &nentry->rule.rlist); + list_replace_rcu(&entry->list, &nentry->list); + } + call_rcu(&entry->rcu, audit_free_rule_rcu); } } + mutex_unlock(&audit_filter_mutex); return err; diff --git a/trunk/kernel/auditsc.c b/trunk/kernel/auditsc.c index 8cbddff6c283..4819f3711973 100644 --- a/trunk/kernel/auditsc.c +++ b/trunk/kernel/auditsc.c @@ -124,6 +124,43 @@ struct audit_aux_data { /* Number of target pids per aux struct. */ #define AUDIT_AUX_PIDS 16 +struct audit_aux_data_mq_open { + struct audit_aux_data d; + int oflag; + mode_t mode; + struct mq_attr attr; +}; + +struct audit_aux_data_mq_sendrecv { + struct audit_aux_data d; + mqd_t mqdes; + size_t msg_len; + unsigned int msg_prio; + struct timespec abs_timeout; +}; + +struct audit_aux_data_mq_notify { + struct audit_aux_data d; + mqd_t mqdes; + struct sigevent notification; +}; + +struct audit_aux_data_mq_getsetattr { + struct audit_aux_data d; + mqd_t mqdes; + struct mq_attr mqstat; +}; + +struct audit_aux_data_ipcctl { + struct audit_aux_data d; + struct ipc_perm p; + unsigned long qbytes; + uid_t uid; + gid_t gid; + mode_t mode; + u32 osid; +}; + struct audit_aux_data_execve { struct audit_aux_data d; int argc; @@ -131,6 +168,23 @@ struct audit_aux_data_execve { struct mm_struct *mm; }; +struct audit_aux_data_socketcall { + struct audit_aux_data d; + int nargs; + unsigned long args[0]; +}; + +struct audit_aux_data_sockaddr { + struct audit_aux_data d; + int len; + char a[0]; +}; + +struct audit_aux_data_fd_pair { + struct audit_aux_data d; + int fd[2]; +}; + struct audit_aux_data_pids { struct audit_aux_data d; pid_t target_pid[AUDIT_AUX_PIDS]; @@ -165,14 +219,14 @@ struct audit_tree_refs { struct audit_context { int dummy; /* must be the first element */ int in_syscall; /* 1 if task is in a syscall */ - enum audit_state state, current_state; + enum audit_state state; unsigned int serial; /* serial number for record */ struct timespec ctime; /* time of syscall entry */ int major; /* syscall number */ unsigned long argv[4]; /* syscall arguments */ int return_valid; /* return code is valid */ long return_code;/* syscall return code */ - u64 prio; + int auditable; /* 1 if record should be written */ int name_count; struct audit_names names[AUDIT_NAMES]; char * filterkey; /* key for rule that triggered record */ @@ -180,8 +234,7 @@ struct audit_context { struct audit_context *previous; /* For nested syscalls */ struct audit_aux_data *aux; struct audit_aux_data *aux_pids; - struct sockaddr_storage *sockaddr; - size_t sockaddr_len; + /* Save things to print about task_struct */ pid_t pid, ppid; uid_t uid, euid, suid, fsuid; @@ -199,49 +252,6 @@ struct audit_context { struct audit_tree_refs *trees, *first_trees; int tree_count; - int type; - union { - struct { - int nargs; - long args[6]; - } socketcall; - struct { - uid_t uid; - gid_t gid; - mode_t mode; - u32 osid; - int has_perm; - uid_t perm_uid; - gid_t perm_gid; - mode_t perm_mode; - unsigned long qbytes; - } ipc; - struct { - mqd_t mqdes; - struct mq_attr mqstat; - } mq_getsetattr; - struct { - mqd_t mqdes; - int sigev_signo; - } mq_notify; - struct { - mqd_t mqdes; - size_t msg_len; - unsigned int msg_prio; - struct timespec abs_timeout; - } mq_sendrecv; - struct { - int oflag; - mode_t mode; - struct mq_attr attr; - } mq_open; - struct { - pid_t pid; - struct audit_cap_data cap; - } capset; - }; - int fds[2]; - #if AUDIT_DEBUG int put_count; int ino_count; @@ -598,12 +608,19 @@ static int audit_filter_rules(struct task_struct *tsk, } } /* Find ipc objects that match */ - if (!ctx || ctx->type != AUDIT_IPC) - break; - if (security_audit_rule_match(ctx->ipc.osid, - f->type, f->op, - f->lsm_rule, ctx)) - ++result; + if (ctx) { + struct audit_aux_data *aux; + for (aux = ctx->aux; aux; + aux = aux->next) { + if (aux->type == AUDIT_IPC) { + struct audit_aux_data_ipcctl *axi = (void *)aux; + if (security_audit_rule_match(axi->osid, f->type, f->op, f->lsm_rule, ctx)) { + ++result; + break; + } + } + } + } } break; case AUDIT_ARG0: @@ -630,16 +647,8 @@ static int audit_filter_rules(struct task_struct *tsk, return 0; } } - - if (ctx) { - if (rule->prio <= ctx->prio) - return 0; - if (rule->filterkey) { - kfree(ctx->filterkey); - ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); - } - ctx->prio = rule->prio; - } + if (rule->filterkey && ctx) + ctx->filterkey = kstrdup(rule->filterkey, GFP_ATOMIC); switch (rule->action) { case AUDIT_NEVER: *state = AUDIT_DISABLED; break; case AUDIT_ALWAYS: *state = AUDIT_RECORD_CONTEXT; break; @@ -652,7 +661,7 @@ static int audit_filter_rules(struct task_struct *tsk, * completely disabled for this task. Since we only have the task * structure at this point, we can only check uid and gid. */ -static enum audit_state audit_filter_task(struct task_struct *tsk, char **key) +static enum audit_state audit_filter_task(struct task_struct *tsk) { struct audit_entry *e; enum audit_state state; @@ -660,8 +669,6 @@ static enum audit_state audit_filter_task(struct task_struct *tsk, char **key) rcu_read_lock(); list_for_each_entry_rcu(e, &audit_filter_list[AUDIT_FILTER_TASK], list) { if (audit_filter_rules(tsk, &e->rule, NULL, NULL, &state)) { - if (state == AUDIT_RECORD_CONTEXT) - *key = kstrdup(e->rule.filterkey, GFP_ATOMIC); rcu_read_unlock(); return state; } @@ -695,7 +702,6 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk, audit_filter_rules(tsk, &e->rule, ctx, NULL, &state)) { rcu_read_unlock(); - ctx->current_state = state; return state; } } @@ -709,14 +715,15 @@ static enum audit_state audit_filter_syscall(struct task_struct *tsk, * buckets applicable to the inode numbers in audit_names[]. * Regarding audit_state, same rules apply as for audit_filter_syscall(). */ -void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx) +enum audit_state audit_filter_inodes(struct task_struct *tsk, + struct audit_context *ctx) { int i; struct audit_entry *e; enum audit_state state; if (audit_pid && tsk->tgid == audit_pid) - return; + return AUDIT_DISABLED; rcu_read_lock(); for (i = 0; i < ctx->name_count; i++) { @@ -733,20 +740,17 @@ void audit_filter_inodes(struct task_struct *tsk, struct audit_context *ctx) if ((e->rule.mask[word] & bit) == bit && audit_filter_rules(tsk, &e->rule, ctx, n, &state)) { rcu_read_unlock(); - ctx->current_state = state; - return; + return state; } } } rcu_read_unlock(); + return AUDIT_BUILD_CONTEXT; } -static void audit_set_auditable(struct audit_context *ctx) +void audit_set_auditable(struct audit_context *ctx) { - if (!ctx->prio) { - ctx->prio = 1; - ctx->current_state = AUDIT_RECORD_CONTEXT; - } + ctx->auditable = 1; } static inline struct audit_context *audit_get_context(struct task_struct *tsk, @@ -777,11 +781,23 @@ static inline struct audit_context *audit_get_context(struct task_struct *tsk, else context->return_code = return_code; - if (context->in_syscall && !context->dummy) { - audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); - audit_filter_inodes(tsk, context); + if (context->in_syscall && !context->dummy && !context->auditable) { + enum audit_state state; + + state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_EXIT]); + if (state == AUDIT_RECORD_CONTEXT) { + context->auditable = 1; + goto get_context; + } + + state = audit_filter_inodes(tsk, context); + if (state == AUDIT_RECORD_CONTEXT) + context->auditable = 1; + } +get_context: + tsk->audit_context = NULL; return context; } @@ -791,7 +807,8 @@ static inline void audit_free_names(struct audit_context *context) int i; #if AUDIT_DEBUG == 2 - if (context->put_count + context->ino_count != context->name_count) { + if (context->auditable + ||context->put_count + context->ino_count != context->name_count) { printk(KERN_ERR "%s:%d(:%d): major=%d in_syscall=%d" " name_count=%d put_count=%d" " ino_count=%d [NOT freeing]\n", @@ -842,7 +859,6 @@ static inline void audit_zero_context(struct audit_context *context, { memset(context, 0, sizeof(*context)); context->state = state; - context->prio = state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; } static inline struct audit_context *audit_alloc_context(enum audit_state state) @@ -868,21 +884,18 @@ int audit_alloc(struct task_struct *tsk) { struct audit_context *context; enum audit_state state; - char *key = NULL; if (likely(!audit_ever_enabled)) return 0; /* Return if not auditing. */ - state = audit_filter_task(tsk, &key); + state = audit_filter_task(tsk); if (likely(state == AUDIT_DISABLED)) return 0; if (!(context = audit_alloc_context(state))) { - kfree(key); audit_log_lost("out of memory in audit_alloc"); return -ENOMEM; } - context->filterkey = key; tsk->audit_context = context; set_tsk_thread_flag(tsk, TIF_SYSCALL_AUDIT); @@ -908,7 +921,6 @@ static inline void audit_free_context(struct audit_context *context) free_tree_refs(context); audit_free_aux(context); kfree(context->filterkey); - kfree(context->sockaddr); kfree(context); context = previous; } while (context); @@ -1218,97 +1230,6 @@ static void audit_log_fcaps(struct audit_buffer *ab, struct audit_names *name) audit_log_format(ab, " cap_fe=%d cap_fver=%x", name->fcap.fE, name->fcap_ver); } -static void show_special(struct audit_context *context, int *call_panic) -{ - struct audit_buffer *ab; - int i; - - ab = audit_log_start(context, GFP_KERNEL, context->type); - if (!ab) - return; - - switch (context->type) { - case AUDIT_SOCKETCALL: { - int nargs = context->socketcall.nargs; - audit_log_format(ab, "nargs=%d", nargs); - for (i = 0; i < nargs; i++) - audit_log_format(ab, " a%d=%lx", i, - context->socketcall.args[i]); - break; } - case AUDIT_IPC: { - u32 osid = context->ipc.osid; - - audit_log_format(ab, "ouid=%u ogid=%u mode=%#o", - context->ipc.uid, context->ipc.gid, context->ipc.mode); - if (osid) { - char *ctx = NULL; - u32 len; - if (security_secid_to_secctx(osid, &ctx, &len)) { - audit_log_format(ab, " osid=%u", osid); - *call_panic = 1; - } else { - audit_log_format(ab, " obj=%s", ctx); - security_release_secctx(ctx, len); - } - } - if (context->ipc.has_perm) { - audit_log_end(ab); - ab = audit_log_start(context, GFP_KERNEL, - AUDIT_IPC_SET_PERM); - audit_log_format(ab, - "qbytes=%lx ouid=%u ogid=%u mode=%#o", - context->ipc.qbytes, - context->ipc.perm_uid, - context->ipc.perm_gid, - context->ipc.perm_mode); - if (!ab) - return; - } - break; } - case AUDIT_MQ_OPEN: { - audit_log_format(ab, - "oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld " - "mq_msgsize=%ld mq_curmsgs=%ld", - context->mq_open.oflag, context->mq_open.mode, - context->mq_open.attr.mq_flags, - context->mq_open.attr.mq_maxmsg, - context->mq_open.attr.mq_msgsize, - context->mq_open.attr.mq_curmsgs); - break; } - case AUDIT_MQ_SENDRECV: { - audit_log_format(ab, - "mqdes=%d msg_len=%zd msg_prio=%u " - "abs_timeout_sec=%ld abs_timeout_nsec=%ld", - context->mq_sendrecv.mqdes, - context->mq_sendrecv.msg_len, - context->mq_sendrecv.msg_prio, - context->mq_sendrecv.abs_timeout.tv_sec, - context->mq_sendrecv.abs_timeout.tv_nsec); - break; } - case AUDIT_MQ_NOTIFY: { - audit_log_format(ab, "mqdes=%d sigev_signo=%d", - context->mq_notify.mqdes, - context->mq_notify.sigev_signo); - break; } - case AUDIT_MQ_GETSETATTR: { - struct mq_attr *attr = &context->mq_getsetattr.mqstat; - audit_log_format(ab, - "mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld " - "mq_curmsgs=%ld ", - context->mq_getsetattr.mqdes, - attr->mq_flags, attr->mq_maxmsg, - attr->mq_msgsize, attr->mq_curmsgs); - break; } - case AUDIT_CAPSET: { - audit_log_format(ab, "pid=%d", context->capset.pid); - audit_log_cap(ab, "cap_pi", &context->capset.cap.inheritable); - audit_log_cap(ab, "cap_pp", &context->capset.cap.permitted); - audit_log_cap(ab, "cap_pe", &context->capset.cap.effective); - break; } - } - audit_log_end(ab); -} - static void audit_log_exit(struct audit_context *context, struct task_struct *tsk) { const struct cred *cred; @@ -1386,12 +1307,94 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts continue; /* audit_panic has been called */ switch (aux->type) { + case AUDIT_MQ_OPEN: { + struct audit_aux_data_mq_open *axi = (void *)aux; + audit_log_format(ab, + "oflag=0x%x mode=%#o mq_flags=0x%lx mq_maxmsg=%ld " + "mq_msgsize=%ld mq_curmsgs=%ld", + axi->oflag, axi->mode, axi->attr.mq_flags, + axi->attr.mq_maxmsg, axi->attr.mq_msgsize, + axi->attr.mq_curmsgs); + break; } + + case AUDIT_MQ_SENDRECV: { + struct audit_aux_data_mq_sendrecv *axi = (void *)aux; + audit_log_format(ab, + "mqdes=%d msg_len=%zd msg_prio=%u " + "abs_timeout_sec=%ld abs_timeout_nsec=%ld", + axi->mqdes, axi->msg_len, axi->msg_prio, + axi->abs_timeout.tv_sec, axi->abs_timeout.tv_nsec); + break; } + + case AUDIT_MQ_NOTIFY: { + struct audit_aux_data_mq_notify *axi = (void *)aux; + audit_log_format(ab, + "mqdes=%d sigev_signo=%d", + axi->mqdes, + axi->notification.sigev_signo); + break; } + + case AUDIT_MQ_GETSETATTR: { + struct audit_aux_data_mq_getsetattr *axi = (void *)aux; + audit_log_format(ab, + "mqdes=%d mq_flags=0x%lx mq_maxmsg=%ld mq_msgsize=%ld " + "mq_curmsgs=%ld ", + axi->mqdes, + axi->mqstat.mq_flags, axi->mqstat.mq_maxmsg, + axi->mqstat.mq_msgsize, axi->mqstat.mq_curmsgs); + break; } + + case AUDIT_IPC: { + struct audit_aux_data_ipcctl *axi = (void *)aux; + audit_log_format(ab, + "ouid=%u ogid=%u mode=%#o", + axi->uid, axi->gid, axi->mode); + if (axi->osid != 0) { + char *ctx = NULL; + u32 len; + if (security_secid_to_secctx( + axi->osid, &ctx, &len)) { + audit_log_format(ab, " osid=%u", + axi->osid); + call_panic = 1; + } else { + audit_log_format(ab, " obj=%s", ctx); + security_release_secctx(ctx, len); + } + } + break; } + + case AUDIT_IPC_SET_PERM: { + struct audit_aux_data_ipcctl *axi = (void *)aux; + audit_log_format(ab, + "qbytes=%lx ouid=%u ogid=%u mode=%#o", + axi->qbytes, axi->uid, axi->gid, axi->mode); + break; } case AUDIT_EXECVE: { struct audit_aux_data_execve *axi = (void *)aux; audit_log_execve_info(context, &ab, axi); break; } + case AUDIT_SOCKETCALL: { + struct audit_aux_data_socketcall *axs = (void *)aux; + audit_log_format(ab, "nargs=%d", axs->nargs); + for (i=0; inargs; i++) + audit_log_format(ab, " a%d=%lx", i, axs->args[i]); + break; } + + case AUDIT_SOCKADDR: { + struct audit_aux_data_sockaddr *axs = (void *)aux; + + audit_log_format(ab, "saddr="); + audit_log_n_hex(ab, axs->a, axs->len); + break; } + + case AUDIT_FD_PAIR: { + struct audit_aux_data_fd_pair *axs = (void *)aux; + audit_log_format(ab, "fd0=%d fd1=%d", axs->fd[0], axs->fd[1]); + break; } + case AUDIT_BPRM_FCAPS: { struct audit_aux_data_bprm_fcaps *axs = (void *)aux; audit_log_format(ab, "fver=%x", axs->fcap_ver); @@ -1406,30 +1409,16 @@ static void audit_log_exit(struct audit_context *context, struct task_struct *ts audit_log_cap(ab, "new_pe", &axs->new_pcap.effective); break; } - } - audit_log_end(ab); - } - - if (context->type) - show_special(context, &call_panic); - - if (context->fds[0] >= 0) { - ab = audit_log_start(context, GFP_KERNEL, AUDIT_FD_PAIR); - if (ab) { - audit_log_format(ab, "fd0=%d fd1=%d", - context->fds[0], context->fds[1]); - audit_log_end(ab); - } - } + case AUDIT_CAPSET: { + struct audit_aux_data_capset *axs = (void *)aux; + audit_log_format(ab, "pid=%d", axs->pid); + audit_log_cap(ab, "cap_pi", &axs->cap.inheritable); + audit_log_cap(ab, "cap_pp", &axs->cap.permitted); + audit_log_cap(ab, "cap_pe", &axs->cap.effective); + break; } - if (context->sockaddr_len) { - ab = audit_log_start(context, GFP_KERNEL, AUDIT_SOCKADDR); - if (ab) { - audit_log_format(ab, "saddr="); - audit_log_n_hex(ab, (void *)context->sockaddr, - context->sockaddr_len); - audit_log_end(ab); } + audit_log_end(ab); } for (aux = context->aux_pids; aux; aux = aux->next) { @@ -1547,7 +1536,7 @@ void audit_free(struct task_struct *tsk) * We use GFP_ATOMIC here because we might be doing this * in the context of the idle thread */ /* that can happen only if we are called from do_exit() */ - if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) + if (context->in_syscall && context->auditable) audit_log_exit(context, tsk); audit_free_context(context); @@ -1631,17 +1620,15 @@ void audit_syscall_entry(int arch, int major, state = context->state; context->dummy = !audit_n_rules; - if (!context->dummy && state == AUDIT_BUILD_CONTEXT) { - context->prio = 0; + if (!context->dummy && (state == AUDIT_SETUP_CONTEXT || state == AUDIT_BUILD_CONTEXT)) state = audit_filter_syscall(tsk, context, &audit_filter_list[AUDIT_FILTER_ENTRY]); - } if (likely(state == AUDIT_DISABLED)) return; context->serial = 0; context->ctime = CURRENT_TIME; context->in_syscall = 1; - context->current_state = state; + context->auditable = !!(state == AUDIT_RECORD_CONTEXT); context->ppid = 0; } @@ -1649,20 +1636,17 @@ void audit_finish_fork(struct task_struct *child) { struct audit_context *ctx = current->audit_context; struct audit_context *p = child->audit_context; - if (!p || !ctx) - return; - if (!ctx->in_syscall || ctx->current_state != AUDIT_RECORD_CONTEXT) + if (!p || !ctx || !ctx->auditable) return; p->arch = ctx->arch; p->major = ctx->major; memcpy(p->argv, ctx->argv, sizeof(ctx->argv)); p->ctime = ctx->ctime; p->dummy = ctx->dummy; + p->auditable = ctx->auditable; p->in_syscall = ctx->in_syscall; p->filterkey = kstrdup(ctx->filterkey, GFP_KERNEL); p->ppid = current->pid; - p->prio = ctx->prio; - p->current_state = ctx->current_state; } /** @@ -1686,11 +1670,11 @@ void audit_syscall_exit(int valid, long return_code) if (likely(!context)) return; - if (context->in_syscall && context->current_state == AUDIT_RECORD_CONTEXT) + if (context->in_syscall && context->auditable) audit_log_exit(context, tsk); context->in_syscall = 0; - context->prio = context->state == AUDIT_RECORD_CONTEXT ? ~0ULL : 0; + context->auditable = 0; if (context->previous) { struct audit_context *new_context = context->previous; @@ -1705,13 +1689,8 @@ void audit_syscall_exit(int valid, long return_code) context->aux_pids = NULL; context->target_pid = 0; context->target_sid = 0; - context->sockaddr_len = 0; - context->type = 0; - context->fds[0] = -1; - if (context->state != AUDIT_RECORD_CONTEXT) { - kfree(context->filterkey); - context->filterkey = NULL; - } + kfree(context->filterkey); + context->filterkey = NULL; tsk->audit_context = context; } } @@ -2102,10 +2081,7 @@ int auditsc_get_stamp(struct audit_context *ctx, t->tv_sec = ctx->ctime.tv_sec; t->tv_nsec = ctx->ctime.tv_nsec; *serial = ctx->serial; - if (!ctx->prio) { - ctx->prio = 1; - ctx->current_state = AUDIT_RECORD_CONTEXT; - } + ctx->auditable = 1; return 1; } @@ -2151,46 +2127,132 @@ int audit_set_loginuid(struct task_struct *task, uid_t loginuid) * @mode: mode bits * @u_attr: queue attributes * + * Returns 0 for success or NULL context or < 0 on error. */ -void __audit_mq_open(int oflag, mode_t mode, struct mq_attr *attr) +int __audit_mq_open(int oflag, mode_t mode, struct mq_attr __user *u_attr) { + struct audit_aux_data_mq_open *ax; struct audit_context *context = current->audit_context; - if (attr) - memcpy(&context->mq_open.attr, attr, sizeof(struct mq_attr)); - else - memset(&context->mq_open.attr, 0, sizeof(struct mq_attr)); + if (!audit_enabled) + return 0; - context->mq_open.oflag = oflag; - context->mq_open.mode = mode; + if (likely(!context)) + return 0; + + ax = kmalloc(sizeof(*ax), GFP_ATOMIC); + if (!ax) + return -ENOMEM; + + if (u_attr != NULL) { + if (copy_from_user(&ax->attr, u_attr, sizeof(ax->attr))) { + kfree(ax); + return -EFAULT; + } + } else + memset(&ax->attr, 0, sizeof(ax->attr)); + + ax->oflag = oflag; + ax->mode = mode; - context->type = AUDIT_MQ_OPEN; + ax->d.type = AUDIT_MQ_OPEN; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; } /** - * __audit_mq_sendrecv - record audit data for a POSIX MQ timed send/receive + * __audit_mq_timedsend - record audit data for a POSIX MQ timed send * @mqdes: MQ descriptor * @msg_len: Message length * @msg_prio: Message priority - * @abs_timeout: Message timeout in absolute time + * @u_abs_timeout: Message timeout in absolute time * + * Returns 0 for success or NULL context or < 0 on error. */ -void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, - const struct timespec *abs_timeout) +int __audit_mq_timedsend(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, + const struct timespec __user *u_abs_timeout) { + struct audit_aux_data_mq_sendrecv *ax; struct audit_context *context = current->audit_context; - struct timespec *p = &context->mq_sendrecv.abs_timeout; - if (abs_timeout) - memcpy(p, abs_timeout, sizeof(struct timespec)); - else - memset(p, 0, sizeof(struct timespec)); + if (!audit_enabled) + return 0; - context->mq_sendrecv.mqdes = mqdes; - context->mq_sendrecv.msg_len = msg_len; - context->mq_sendrecv.msg_prio = msg_prio; + if (likely(!context)) + return 0; - context->type = AUDIT_MQ_SENDRECV; + ax = kmalloc(sizeof(*ax), GFP_ATOMIC); + if (!ax) + return -ENOMEM; + + if (u_abs_timeout != NULL) { + if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) { + kfree(ax); + return -EFAULT; + } + } else + memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout)); + + ax->mqdes = mqdes; + ax->msg_len = msg_len; + ax->msg_prio = msg_prio; + + ax->d.type = AUDIT_MQ_SENDRECV; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; +} + +/** + * __audit_mq_timedreceive - record audit data for a POSIX MQ timed receive + * @mqdes: MQ descriptor + * @msg_len: Message length + * @u_msg_prio: Message priority + * @u_abs_timeout: Message timeout in absolute time + * + * Returns 0 for success or NULL context or < 0 on error. + */ +int __audit_mq_timedreceive(mqd_t mqdes, size_t msg_len, + unsigned int __user *u_msg_prio, + const struct timespec __user *u_abs_timeout) +{ + struct audit_aux_data_mq_sendrecv *ax; + struct audit_context *context = current->audit_context; + + if (!audit_enabled) + return 0; + + if (likely(!context)) + return 0; + + ax = kmalloc(sizeof(*ax), GFP_ATOMIC); + if (!ax) + return -ENOMEM; + + if (u_msg_prio != NULL) { + if (get_user(ax->msg_prio, u_msg_prio)) { + kfree(ax); + return -EFAULT; + } + } else + ax->msg_prio = 0; + + if (u_abs_timeout != NULL) { + if (copy_from_user(&ax->abs_timeout, u_abs_timeout, sizeof(ax->abs_timeout))) { + kfree(ax); + return -EFAULT; + } + } else + memset(&ax->abs_timeout, 0, sizeof(ax->abs_timeout)); + + ax->mqdes = mqdes; + ax->msg_len = msg_len; + + ax->d.type = AUDIT_MQ_SENDRECV; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; } /** @@ -2198,19 +2260,38 @@ void __audit_mq_sendrecv(mqd_t mqdes, size_t msg_len, unsigned int msg_prio, * @mqdes: MQ descriptor * @u_notification: Notification event * + * Returns 0 for success or NULL context or < 0 on error. */ -void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification) +int __audit_mq_notify(mqd_t mqdes, const struct sigevent __user *u_notification) { + struct audit_aux_data_mq_notify *ax; struct audit_context *context = current->audit_context; - if (notification) - context->mq_notify.sigev_signo = notification->sigev_signo; - else - context->mq_notify.sigev_signo = 0; + if (!audit_enabled) + return 0; + + if (likely(!context)) + return 0; + + ax = kmalloc(sizeof(*ax), GFP_ATOMIC); + if (!ax) + return -ENOMEM; - context->mq_notify.mqdes = mqdes; - context->type = AUDIT_MQ_NOTIFY; + if (u_notification != NULL) { + if (copy_from_user(&ax->notification, u_notification, sizeof(ax->notification))) { + kfree(ax); + return -EFAULT; + } + } else + memset(&ax->notification, 0, sizeof(ax->notification)); + + ax->mqdes = mqdes; + + ax->d.type = AUDIT_MQ_NOTIFY; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; } /** @@ -2218,29 +2299,55 @@ void __audit_mq_notify(mqd_t mqdes, const struct sigevent *notification) * @mqdes: MQ descriptor * @mqstat: MQ flags * + * Returns 0 for success or NULL context or < 0 on error. */ -void __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) +int __audit_mq_getsetattr(mqd_t mqdes, struct mq_attr *mqstat) { + struct audit_aux_data_mq_getsetattr *ax; struct audit_context *context = current->audit_context; - context->mq_getsetattr.mqdes = mqdes; - context->mq_getsetattr.mqstat = *mqstat; - context->type = AUDIT_MQ_GETSETATTR; + + if (!audit_enabled) + return 0; + + if (likely(!context)) + return 0; + + ax = kmalloc(sizeof(*ax), GFP_ATOMIC); + if (!ax) + return -ENOMEM; + + ax->mqdes = mqdes; + ax->mqstat = *mqstat; + + ax->d.type = AUDIT_MQ_GETSETATTR; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; } /** * audit_ipc_obj - record audit data for ipc object * @ipcp: ipc permissions * + * Returns 0 for success or NULL context or < 0 on error. */ -void __audit_ipc_obj(struct kern_ipc_perm *ipcp) +int __audit_ipc_obj(struct kern_ipc_perm *ipcp) { + struct audit_aux_data_ipcctl *ax; struct audit_context *context = current->audit_context; - context->ipc.uid = ipcp->uid; - context->ipc.gid = ipcp->gid; - context->ipc.mode = ipcp->mode; - context->ipc.has_perm = 0; - security_ipc_getsecid(ipcp, &context->ipc.osid); - context->type = AUDIT_IPC; + + ax = kmalloc(sizeof(*ax), GFP_ATOMIC); + if (!ax) + return -ENOMEM; + + ax->uid = ipcp->uid; + ax->gid = ipcp->gid; + ax->mode = ipcp->mode; + security_ipc_getsecid(ipcp, &ax->osid); + ax->d.type = AUDIT_IPC; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; } /** @@ -2250,17 +2357,26 @@ void __audit_ipc_obj(struct kern_ipc_perm *ipcp) * @gid: msgq group id * @mode: msgq mode (permissions) * - * Called only after audit_ipc_obj(). + * Returns 0 for success or NULL context or < 0 on error. */ -void __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) +int __audit_ipc_set_perm(unsigned long qbytes, uid_t uid, gid_t gid, mode_t mode) { + struct audit_aux_data_ipcctl *ax; struct audit_context *context = current->audit_context; - context->ipc.qbytes = qbytes; - context->ipc.perm_uid = uid; - context->ipc.perm_gid = gid; - context->ipc.perm_mode = mode; - context->ipc.has_perm = 1; + ax = kmalloc(sizeof(*ax), GFP_ATOMIC); + if (!ax) + return -ENOMEM; + + ax->qbytes = qbytes; + ax->uid = uid; + ax->gid = gid; + ax->mode = mode; + + ax->d.type = AUDIT_IPC_SET_PERM; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; } int audit_bprm(struct linux_binprm *bprm) @@ -2290,17 +2406,27 @@ int audit_bprm(struct linux_binprm *bprm) * @nargs: number of args * @args: args array * + * Returns 0 for success or NULL context or < 0 on error. */ -void audit_socketcall(int nargs, unsigned long *args) +int audit_socketcall(int nargs, unsigned long *args) { + struct audit_aux_data_socketcall *ax; struct audit_context *context = current->audit_context; if (likely(!context || context->dummy)) - return; + return 0; - context->type = AUDIT_SOCKETCALL; - context->socketcall.nargs = nargs; - memcpy(context->socketcall.args, args, nargs * sizeof(unsigned long)); + ax = kmalloc(sizeof(*ax) + nargs * sizeof(unsigned long), GFP_KERNEL); + if (!ax) + return -ENOMEM; + + ax->nargs = nargs; + memcpy(ax->args, args, nargs * sizeof(unsigned long)); + + ax->d.type = AUDIT_SOCKETCALL; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; } /** @@ -2308,12 +2434,29 @@ void audit_socketcall(int nargs, unsigned long *args) * @fd1: the first file descriptor * @fd2: the second file descriptor * + * Returns 0 for success or NULL context or < 0 on error. */ -void __audit_fd_pair(int fd1, int fd2) +int __audit_fd_pair(int fd1, int fd2) { struct audit_context *context = current->audit_context; - context->fds[0] = fd1; - context->fds[1] = fd2; + struct audit_aux_data_fd_pair *ax; + + if (likely(!context)) { + return 0; + } + + ax = kmalloc(sizeof(*ax), GFP_KERNEL); + if (!ax) { + return -ENOMEM; + } + + ax->fd[0] = fd1; + ax->fd[1] = fd2; + + ax->d.type = AUDIT_FD_PAIR; + ax->d.next = context->aux; + context->aux = (void *)ax; + return 0; } /** @@ -2325,20 +2468,22 @@ void __audit_fd_pair(int fd1, int fd2) */ int audit_sockaddr(int len, void *a) { + struct audit_aux_data_sockaddr *ax; struct audit_context *context = current->audit_context; if (likely(!context || context->dummy)) return 0; - if (!context->sockaddr) { - void *p = kmalloc(sizeof(struct sockaddr_storage), GFP_KERNEL); - if (!p) - return -ENOMEM; - context->sockaddr = p; - } + ax = kmalloc(sizeof(*ax) + len, GFP_KERNEL); + if (!ax) + return -ENOMEM; - context->sockaddr_len = len; - memcpy(context->sockaddr, a, len); + ax->len = len; + memcpy(ax->a, a, len); + + ax->d.type = AUDIT_SOCKADDR; + ax->d.next = context->aux; + context->aux = (void *)ax; return 0; } @@ -2472,15 +2617,29 @@ int __audit_log_bprm_fcaps(struct linux_binprm *bprm, * Record the aguments userspace sent to sys_capset for later printing by the * audit system if applicable */ -void __audit_log_capset(pid_t pid, +int __audit_log_capset(pid_t pid, const struct cred *new, const struct cred *old) { + struct audit_aux_data_capset *ax; struct audit_context *context = current->audit_context; - context->capset.pid = pid; - context->capset.cap.effective = new->cap_effective; - context->capset.cap.inheritable = new->cap_effective; - context->capset.cap.permitted = new->cap_permitted; - context->type = AUDIT_CAPSET; + + if (likely(!audit_enabled || !context || context->dummy)) + return 0; + + ax = kmalloc(sizeof(*ax), GFP_KERNEL); + if (!ax) + return -ENOMEM; + + ax->d.type = AUDIT_CAPSET; + ax->d.next = context->aux; + context->aux = (void *)ax; + + ax->pid = pid; + ax->cap.effective = new->cap_effective; + ax->cap.inheritable = new->cap_effective; + ax->cap.permitted = new->cap_permitted; + + return 0; } /** diff --git a/trunk/kernel/capability.c b/trunk/kernel/capability.c index c598d9d5be4f..36b4b4daebec 100644 --- a/trunk/kernel/capability.c +++ b/trunk/kernel/capability.c @@ -280,7 +280,9 @@ asmlinkage long sys_capset(cap_user_header_t header, const cap_user_data_t data) if (ret < 0) goto error; - audit_log_capset(pid, new, current_cred()); + ret = audit_log_capset(pid, new, current_cred()); + if (ret < 0) + return ret; return commit_creds(new); diff --git a/trunk/kernel/cgroup.c b/trunk/kernel/cgroup.c index 891a84eb9d30..48348dde6d81 100644 --- a/trunk/kernel/cgroup.c +++ b/trunk/kernel/cgroup.c @@ -2945,11 +2945,7 @@ int cgroup_clone(struct task_struct *tsk, struct cgroup_subsys *subsys, parent = task_cgroup(tsk, subsys->subsys_id); /* Pin the hierarchy */ - if (!atomic_inc_not_zero(&parent->root->sb->s_active)) { - /* We race with the final deactivate_super() */ - mutex_unlock(&cgroup_mutex); - return 0; - } + atomic_inc(&parent->root->sb->s_active); /* Keep the cgroup alive */ get_css_set(cg); diff --git a/trunk/mm/filemap.c b/trunk/mm/filemap.c index f8c69273c37f..f3e5f8944d17 100644 --- a/trunk/mm/filemap.c +++ b/trunk/mm/filemap.c @@ -2140,24 +2140,19 @@ EXPORT_SYMBOL(generic_file_direct_write); * Find or create a page at the given pagecache position. Return the locked * page. This function is specifically for buffered writes. */ -struct page *grab_cache_page_write_begin(struct address_space *mapping, - pgoff_t index, unsigned flags) +struct page *__grab_cache_page(struct address_space *mapping, pgoff_t index) { int status; struct page *page; - gfp_t gfp_notmask = 0; - if (flags & AOP_FLAG_NOFS) - gfp_notmask = __GFP_FS; repeat: page = find_lock_page(mapping, index); if (likely(page)) return page; - page = __page_cache_alloc(mapping_gfp_mask(mapping) & ~gfp_notmask); + page = page_cache_alloc(mapping); if (!page) return NULL; - status = add_to_page_cache_lru(page, mapping, index, - GFP_KERNEL & ~gfp_notmask); + status = add_to_page_cache_lru(page, mapping, index, GFP_KERNEL); if (unlikely(status)) { page_cache_release(page); if (status == -EEXIST) @@ -2166,7 +2161,7 @@ struct page *grab_cache_page_write_begin(struct address_space *mapping, } return page; } -EXPORT_SYMBOL(grab_cache_page_write_begin); +EXPORT_SYMBOL(__grab_cache_page); static ssize_t generic_perform_write(struct file *file, struct iov_iter *i, loff_t pos) diff --git a/trunk/mm/mmap.c b/trunk/mm/mmap.c index 2c778fcfd9bd..d4855a682ab6 100644 --- a/trunk/mm/mmap.c +++ b/trunk/mm/mmap.c @@ -3,7 +3,7 @@ * * Written by obz. * - * Address space accounting code + * Address space accounting code */ #include diff --git a/trunk/mm/mprotect.c b/trunk/mm/mprotect.c index cfb4c4852062..fded06f923f4 100644 --- a/trunk/mm/mprotect.c +++ b/trunk/mm/mprotect.c @@ -4,7 +4,7 @@ * (C) Copyright 1994 Linus Torvalds * (C) Copyright 2002 Christoph Hellwig * - * Address space accounting code + * Address space accounting code * (C) Copyright 2002 Red Hat Inc, All Rights Reserved */ diff --git a/trunk/mm/mremap.c b/trunk/mm/mremap.c index 646de959aa58..58a2908f42f5 100644 --- a/trunk/mm/mremap.c +++ b/trunk/mm/mremap.c @@ -3,7 +3,7 @@ * * (C) Copyright 1996 Linus Torvalds * - * Address space accounting code + * Address space accounting code * (C) Copyright 2002 Red Hat Inc, All Rights Reserved */ diff --git a/trunk/mm/vmalloc.c b/trunk/mm/vmalloc.c index 7465f22fec0c..1ddb77ba3995 100644 --- a/trunk/mm/vmalloc.c +++ b/trunk/mm/vmalloc.c @@ -151,12 +151,11 @@ static int vmap_pud_range(pgd_t *pgd, unsigned long addr, * * Ie. pte at addr+N*PAGE_SIZE shall point to pfn corresponding to pages[N] */ -static int vmap_page_range(unsigned long start, unsigned long end, +static int vmap_page_range(unsigned long addr, unsigned long end, pgprot_t prot, struct page **pages) { pgd_t *pgd; unsigned long next; - unsigned long addr = start; int err = 0; int nr = 0; @@ -168,7 +167,7 @@ static int vmap_page_range(unsigned long start, unsigned long end, if (err) break; } while (pgd++, addr = next, addr != end); - flush_cache_vmap(start, end); + flush_cache_vmap(addr, end); if (unlikely(err)) return err; diff --git a/trunk/net/socket.c b/trunk/net/socket.c index 06603d73c411..2c730fc718ab 100644 --- a/trunk/net/socket.c +++ b/trunk/net/socket.c @@ -1313,7 +1313,13 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, goto out_fd1; } - audit_fd_pair(fd1, fd2); + err = audit_fd_pair(fd1, fd2); + if (err < 0) { + fput(newfile1); + fput(newfile2); + goto out_fd; + } + fd_install(fd1, newfile1); fd_install(fd2, newfile2); /* fd1 and fd2 may be already another descriptors. @@ -1343,6 +1349,7 @@ asmlinkage long sys_socketpair(int family, int type, int protocol, out_fd1: put_filp(newfile2); sock_release(sock2); +out_fd: put_unused_fd(fd1); put_unused_fd(fd2); goto out; @@ -2058,7 +2065,9 @@ asmlinkage long sys_socketcall(int call, unsigned long __user *args) if (copy_from_user(a, args, nargs[call])) return -EFAULT; - audit_socketcall(nargs[call] / sizeof(unsigned long), a); + err = audit_socketcall(nargs[call] / sizeof(unsigned long), a); + if (err) + return err; a0 = a[0]; a1 = a[1]; diff --git a/trunk/security/selinux/ss/services.c b/trunk/security/selinux/ss/services.c index c65e4fe4a0f1..343c8ab14af0 100644 --- a/trunk/security/selinux/ss/services.c +++ b/trunk/security/selinux/ss/services.c @@ -2602,7 +2602,7 @@ int selinux_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) case AUDIT_OBJ_ROLE: case AUDIT_OBJ_TYPE: /* only 'equals' and 'not equals' fit user, role, and type */ - if (op != Audit_equal && op != Audit_not_equal) + if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) return -EINVAL; break; case AUDIT_SUBJ_SEN: @@ -2736,10 +2736,10 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, case AUDIT_SUBJ_USER: case AUDIT_OBJ_USER: switch (op) { - case Audit_equal: + case AUDIT_EQUAL: match = (ctxt->user == rule->au_ctxt.user); break; - case Audit_not_equal: + case AUDIT_NOT_EQUAL: match = (ctxt->user != rule->au_ctxt.user); break; } @@ -2747,10 +2747,10 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, case AUDIT_SUBJ_ROLE: case AUDIT_OBJ_ROLE: switch (op) { - case Audit_equal: + case AUDIT_EQUAL: match = (ctxt->role == rule->au_ctxt.role); break; - case Audit_not_equal: + case AUDIT_NOT_EQUAL: match = (ctxt->role != rule->au_ctxt.role); break; } @@ -2758,10 +2758,10 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, case AUDIT_SUBJ_TYPE: case AUDIT_OBJ_TYPE: switch (op) { - case Audit_equal: + case AUDIT_EQUAL: match = (ctxt->type == rule->au_ctxt.type); break; - case Audit_not_equal: + case AUDIT_NOT_EQUAL: match = (ctxt->type != rule->au_ctxt.type); break; } @@ -2774,31 +2774,31 @@ int selinux_audit_rule_match(u32 sid, u32 field, u32 op, void *vrule, field == AUDIT_OBJ_LEV_LOW) ? &ctxt->range.level[0] : &ctxt->range.level[1]); switch (op) { - case Audit_equal: + case AUDIT_EQUAL: match = mls_level_eq(&rule->au_ctxt.range.level[0], level); break; - case Audit_not_equal: + case AUDIT_NOT_EQUAL: match = !mls_level_eq(&rule->au_ctxt.range.level[0], level); break; - case Audit_lt: + case AUDIT_LESS_THAN: match = (mls_level_dom(&rule->au_ctxt.range.level[0], level) && !mls_level_eq(&rule->au_ctxt.range.level[0], level)); break; - case Audit_le: + case AUDIT_LESS_THAN_OR_EQUAL: match = mls_level_dom(&rule->au_ctxt.range.level[0], level); break; - case Audit_gt: + case AUDIT_GREATER_THAN: match = (mls_level_dom(level, &rule->au_ctxt.range.level[0]) && !mls_level_eq(level, &rule->au_ctxt.range.level[0])); break; - case Audit_ge: + case AUDIT_GREATER_THAN_OR_EQUAL: match = mls_level_dom(level, &rule->au_ctxt.range.level[0]); break; diff --git a/trunk/security/smack/smack_lsm.c b/trunk/security/smack/smack_lsm.c index 848212fd4845..1b5551dfc1f7 100644 --- a/trunk/security/smack/smack_lsm.c +++ b/trunk/security/smack/smack_lsm.c @@ -2492,7 +2492,7 @@ static int smack_audit_rule_init(u32 field, u32 op, char *rulestr, void **vrule) if (field != AUDIT_SUBJ_USER && field != AUDIT_OBJ_USER) return -EINVAL; - if (op != Audit_equal && op != Audit_not_equal) + if (op != AUDIT_EQUAL && op != AUDIT_NOT_EQUAL) return -EINVAL; *rule = smk_import(rulestr, 0); @@ -2556,9 +2556,9 @@ static int smack_audit_rule_match(u32 secid, u32 field, u32 op, void *vrule, * both pointers will point to the same smack_known * label. */ - if (op == Audit_equal) + if (op == AUDIT_EQUAL) return (rule == smack); - if (op == Audit_not_equal) + if (op == AUDIT_NOT_EQUAL) return (rule != smack); return 0;