diff --git a/[refs] b/[refs] index 0d105bfb6a56..aac7e46b3614 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 612b322ade7954a1d984fa410a70d4ae50f75c0d +refs/heads/master: 6887d83d6a537b5002edff7efa1a7c600af0ce26 diff --git a/trunk/arch/sh/kernel/syscalls.S b/trunk/arch/sh/kernel/syscalls.S index 768334e95075..ca81976e9e34 100644 --- a/trunk/arch/sh/kernel/syscalls.S +++ b/trunk/arch/sh/kernel/syscalls.S @@ -351,3 +351,6 @@ ENTRY(sys_call_table) .long sys_sync_file_range .long sys_tee /* 315 */ .long sys_vmsplice + .long sys_move_pages + .long sys_getcpu + .long sys_epoll_pwait diff --git a/trunk/arch/sparc64/kernel/prom.c b/trunk/arch/sparc64/kernel/prom.c index 0917c24c4f08..c60efb3cb22e 100644 --- a/trunk/arch/sparc64/kernel/prom.c +++ b/trunk/arch/sparc64/kernel/prom.c @@ -793,7 +793,7 @@ static unsigned int schizo_irq_build(struct device_node *dp, return virt_irq; } -static void __schizo_irq_trans_init(struct device_node *dp, int is_tomatillo) +static void schizo_irq_trans_init(struct device_node *dp) { struct linux_prom64_registers *regs; struct schizo_irq_data *irq_data; @@ -807,24 +807,11 @@ static void __schizo_irq_trans_init(struct device_node *dp, int is_tomatillo) dp->irq_trans->data = irq_data; irq_data->pbm_regs = regs[0].phys_addr; - if (is_tomatillo) - irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL; - else - irq_data->sync_reg = 0UL; + irq_data->sync_reg = regs[3].phys_addr + 0x1a18UL; irq_data->portid = of_getintprop_default(dp, "portid", 0); irq_data->chip_version = of_getintprop_default(dp, "version#", 0); } -static void schizo_irq_trans_init(struct device_node *dp) -{ - __schizo_irq_trans_init(dp, 0); -} - -static void tomatillo_irq_trans_init(struct device_node *dp) -{ - __schizo_irq_trans_init(dp, 1); -} - static unsigned int pci_sun4v_irq_build(struct device_node *dp, unsigned int devino, void *_data) @@ -1063,8 +1050,8 @@ static struct irq_trans pci_irq_trans_table[] = { { "pci108e,8001", schizo_irq_trans_init }, { "SUNW,schizo+", schizo_irq_trans_init }, { "pci108e,8002", schizo_irq_trans_init }, - { "SUNW,tomatillo", tomatillo_irq_trans_init }, - { "pci108e,a801", tomatillo_irq_trans_init }, + { "SUNW,tomatillo", schizo_irq_trans_init }, + { "pci108e,a801", schizo_irq_trans_init }, { "SUNW,sun4v-pci", pci_sun4v_irq_trans_init }, }; #endif diff --git a/trunk/arch/sparc64/kernel/traps.c b/trunk/arch/sparc64/kernel/traps.c index fe1796c939c3..68420e2dad0e 100644 --- a/trunk/arch/sparc64/kernel/traps.c +++ b/trunk/arch/sparc64/kernel/traps.c @@ -87,7 +87,6 @@ static void dump_tl1_traplog(struct tl1_traplog *p) i + 1, p->trapstack[i].tstate, p->trapstack[i].tpc, p->trapstack[i].tnpc, p->trapstack[i].tt); - print_symbol("TRAPLOG: TPC<%s>\n", p->trapstack[i].tpc); } } @@ -1135,9 +1134,6 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in printk("%s" "ERROR(%d): TPC[%lx] TNPC[%lx] O7[%lx] TSTATE[%lx]\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), regs->tpc, regs->tnpc, regs->u_regs[UREG_I7], regs->tstate); - printk("%s" "ERROR(%d): ", - (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id()); - print_symbol("TPC<%s>\n", regs->tpc); printk("%s" "ERROR(%d): M_SYND(%lx), E_SYND(%lx)%s%s\n", (recoverable ? KERN_WARNING : KERN_CRIT), smp_processor_id(), (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT, @@ -1745,7 +1741,6 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs) smp_processor_id(), (type & 0x1) ? 'I' : 'D', regs->tpc); - print_symbol(KERN_EMERG "TPC<%s>\n", regs->tpc); panic("Irrecoverable Cheetah+ parity error."); } @@ -1753,7 +1748,6 @@ void cheetah_plus_parity_error(int type, struct pt_regs *regs) smp_processor_id(), (type & 0x1) ? 'I' : 'D', regs->tpc); - print_symbol(KERN_WARNING "TPC<%s>\n", regs->tpc); } struct sun4v_error_entry { @@ -1952,7 +1946,6 @@ void sun4v_itlb_error_report(struct pt_regs *regs, int tl) printk(KERN_EMERG "SUN4V-ITLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl); - print_symbol(KERN_EMERG "SUN4V-ITLB: TPC<%s>\n", regs->tpc); printk(KERN_EMERG "SUN4V-ITLB: vaddr[%lx] ctx[%lx] " "pte[%lx] error[%lx]\n", sun4v_err_itlb_vaddr, sun4v_err_itlb_ctx, @@ -1973,7 +1966,6 @@ void sun4v_dtlb_error_report(struct pt_regs *regs, int tl) printk(KERN_EMERG "SUN4V-DTLB: Error at TPC[%lx], tl %d\n", regs->tpc, tl); - print_symbol(KERN_EMERG "SUN4V-DTLB: TPC<%s>\n", regs->tpc); printk(KERN_EMERG "SUN4V-DTLB: vaddr[%lx] ctx[%lx] " "pte[%lx] error[%lx]\n", sun4v_err_dtlb_vaddr, sun4v_err_dtlb_ctx, diff --git a/trunk/arch/um/drivers/ubd_kern.c b/trunk/arch/um/drivers/ubd_kern.c index 49c047b75cc5..bc458f57921b 100644 --- a/trunk/arch/um/drivers/ubd_kern.c +++ b/trunk/arch/um/drivers/ubd_kern.c @@ -106,15 +106,10 @@ static inline void ubd_set_bit(__u64 bit, unsigned char *data) #define DRIVER_NAME "uml-blkdev" -/* Can be taken in interrupt context, and is passed to the block layer to lock - * the request queue. Kernel side code knows that. */ static DEFINE_SPINLOCK(ubd_io_lock); +static DEFINE_SPINLOCK(ubd_lock); -static DEFINE_MUTEX(ubd_lock); - -/* XXX - this made sense in 2.4 days, now it's only used as a boolean, and - * probably it doesn't make sense even for that. */ -static int do_ubd; +static void (*do_ubd)(void); static int ubd_open(struct inode * inode, struct file * filp); static int ubd_release(struct inode * inode, struct file * file); @@ -122,7 +117,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg); static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo); -#define MAX_DEV (16) +#define MAX_DEV (8) static struct block_device_operations ubd_blops = { .owner = THIS_MODULE, @@ -155,9 +150,8 @@ static struct gendisk *fake_gendisk[MAX_DEV]; static struct openflags global_openflags = OPEN_FLAGS; struct cow { - /* backing file name */ + /* This is the backing file, actually */ char *file; - /* backing file fd */ int fd; unsigned long *bitmap; unsigned long bitmap_len; @@ -166,16 +160,14 @@ struct cow { }; struct ubd { - /* name (and fd, below) of the file opened for writing, either the - * backing or the cow file. */ char *file; int count; int fd; __u64 size; struct openflags boot_openflags; struct openflags openflags; - unsigned shared:1; - unsigned no_cow:1; + int shared; + int no_cow; struct cow cow; struct platform_device pdev; }; @@ -200,7 +192,18 @@ struct ubd { .cow = DEFAULT_COW, \ } -struct ubd ubd_devs[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; +struct ubd ubd_dev[MAX_DEV] = { [ 0 ... MAX_DEV - 1 ] = DEFAULT_UBD }; + +static int ubd0_init(void) +{ + struct ubd *dev = &ubd_dev[0]; + + if(dev->file == NULL) + dev->file = "root_fs"; + return(0); +} + +__initcall(ubd0_init); /* Only changed by fake_ide_setup which is a setup */ static int fake_ide = 0; @@ -274,7 +277,7 @@ static int parse_unit(char **ptr) return(-1); *ptr = end; } - else if (('a' <= *str) && (*str <= 'z')) { + else if (('a' <= *str) && (*str <= 'h')) { n = *str - 'a'; str++; *ptr = str; @@ -282,13 +285,9 @@ static int parse_unit(char **ptr) return(n); } -/* If *index_out == -1 at exit, the passed option was a general one; - * otherwise, the str pointer is used (and owned) inside ubd_devs array, so it - * should not be freed on exit. - */ static int ubd_setup_common(char *str, int *index_out) { - struct ubd *ubd_dev; + struct ubd *dev; struct openflags flags = global_openflags; char *backing_file; int n, err, i; @@ -312,7 +311,7 @@ static int ubd_setup_common(char *str, int *index_out) } err = 1; - mutex_lock(&ubd_lock); + spin_lock(&ubd_lock); if(fake_major != MAJOR_NR){ printk(KERN_ERR "Can't assign a fake major twice\n"); goto out1; @@ -324,7 +323,7 @@ static int ubd_setup_common(char *str, int *index_out) major); err = 0; out1: - mutex_unlock(&ubd_lock); + spin_unlock(&ubd_lock); return(err); } @@ -341,10 +340,10 @@ static int ubd_setup_common(char *str, int *index_out) } err = 1; - mutex_lock(&ubd_lock); + spin_lock(&ubd_lock); - ubd_dev = &ubd_devs[n]; - if(ubd_dev->file != NULL){ + dev = &ubd_dev[n]; + if(dev->file != NULL){ printk(KERN_ERR "ubd_setup : device already configured\n"); goto out; } @@ -361,10 +360,10 @@ static int ubd_setup_common(char *str, int *index_out) flags.s = 1; break; case 'd': - ubd_dev->no_cow = 1; + dev->no_cow = 1; break; case 'c': - ubd_dev->shared = 1; + dev->shared = 1; break; case '=': str++; @@ -391,7 +390,7 @@ static int ubd_setup_common(char *str, int *index_out) } if(backing_file){ - if(ubd_dev->no_cow) + if(dev->no_cow) printk(KERN_ERR "Can't specify both 'd' and a " "cow file\n"); else { @@ -399,11 +398,11 @@ static int ubd_setup_common(char *str, int *index_out) backing_file++; } } - ubd_dev->file = str; - ubd_dev->cow.file = backing_file; - ubd_dev->boot_openflags = flags; + dev->file = str; + dev->cow.file = backing_file; + dev->boot_openflags = flags; out: - mutex_unlock(&ubd_lock); + spin_unlock(&ubd_lock); return(err); } @@ -473,9 +472,8 @@ int thread_fd = -1; /* Changed by ubd_handler, which is serialized because interrupts only * happen on CPU 0. - * XXX: currently unused. */ -static int intr_count = 0; +int intr_count = 0; /* call ubd_finish if you need to serialize */ static void __ubd_finish(struct request *req, int error) @@ -495,8 +493,6 @@ static void __ubd_finish(struct request *req, int error) end_request(req, 1); } -/* Callable only from interrupt context - otherwise you need to do - * spin_lock_irq()/spin_lock_irqsave() */ static inline void ubd_finish(struct request *req, int error) { spin_lock(&ubd_io_lock); @@ -504,15 +500,14 @@ static inline void ubd_finish(struct request *req, int error) spin_unlock(&ubd_io_lock); } -/* XXX - move this inside ubd_intr. */ -/* Called without ubd_io_lock held, and only in interrupt context. */ +/* Called without ubd_io_lock held */ static void ubd_handler(void) { struct io_thread_req req; struct request *rq = elv_next_request(ubd_queue); int n; - do_ubd = 0; + do_ubd = NULL; intr_count++; n = os_read_file(thread_fd, &req, sizeof(req)); if(n != sizeof(req)){ @@ -526,9 +521,7 @@ static void ubd_handler(void) ubd_finish(rq, req.error); reactivate_fd(thread_fd, UBD_IRQ); - spin_lock(&ubd_io_lock); do_ubd_request(ubd_queue); - spin_unlock(&ubd_io_lock); } static irqreturn_t ubd_intr(int irq, void *dev) @@ -548,90 +541,87 @@ void kill_io_thread(void) __uml_exitcall(kill_io_thread); -static inline int ubd_file_size(struct ubd *ubd_dev, __u64 *size_out) +static int ubd_file_size(struct ubd *dev, __u64 *size_out) { char *file; - file = ubd_dev->cow.file ? ubd_dev->cow.file : ubd_dev->file; + file = dev->cow.file ? dev->cow.file : dev->file; return(os_file_size(file, size_out)); } -static void ubd_close_dev(struct ubd *ubd_dev) +static void ubd_close(struct ubd *dev) { - os_close_file(ubd_dev->fd); - if(ubd_dev->cow.file == NULL) + os_close_file(dev->fd); + if(dev->cow.file == NULL) return; - os_close_file(ubd_dev->cow.fd); - vfree(ubd_dev->cow.bitmap); - ubd_dev->cow.bitmap = NULL; + os_close_file(dev->cow.fd); + vfree(dev->cow.bitmap); + dev->cow.bitmap = NULL; } -static int ubd_open_dev(struct ubd *ubd_dev) +static int ubd_open_dev(struct ubd *dev) { struct openflags flags; char **back_ptr; int err, create_cow, *create_ptr; - int fd; - ubd_dev->openflags = ubd_dev->boot_openflags; + dev->openflags = dev->boot_openflags; create_cow = 0; - create_ptr = (ubd_dev->cow.file != NULL) ? &create_cow : NULL; - back_ptr = ubd_dev->no_cow ? NULL : &ubd_dev->cow.file; - - fd = open_ubd_file(ubd_dev->file, &ubd_dev->openflags, ubd_dev->shared, - back_ptr, &ubd_dev->cow.bitmap_offset, - &ubd_dev->cow.bitmap_len, &ubd_dev->cow.data_offset, + create_ptr = (dev->cow.file != NULL) ? &create_cow : NULL; + back_ptr = dev->no_cow ? NULL : &dev->cow.file; + dev->fd = open_ubd_file(dev->file, &dev->openflags, dev->shared, + back_ptr, &dev->cow.bitmap_offset, + &dev->cow.bitmap_len, &dev->cow.data_offset, create_ptr); - if((fd == -ENOENT) && create_cow){ - fd = create_cow_file(ubd_dev->file, ubd_dev->cow.file, - ubd_dev->openflags, 1 << 9, PAGE_SIZE, - &ubd_dev->cow.bitmap_offset, - &ubd_dev->cow.bitmap_len, - &ubd_dev->cow.data_offset); - if(fd >= 0){ + if((dev->fd == -ENOENT) && create_cow){ + dev->fd = create_cow_file(dev->file, dev->cow.file, + dev->openflags, 1 << 9, PAGE_SIZE, + &dev->cow.bitmap_offset, + &dev->cow.bitmap_len, + &dev->cow.data_offset); + if(dev->fd >= 0){ printk(KERN_INFO "Creating \"%s\" as COW file for " - "\"%s\"\n", ubd_dev->file, ubd_dev->cow.file); + "\"%s\"\n", dev->file, dev->cow.file); } } - if(fd < 0){ - printk("Failed to open '%s', errno = %d\n", ubd_dev->file, - -fd); - return fd; + if(dev->fd < 0){ + printk("Failed to open '%s', errno = %d\n", dev->file, + -dev->fd); + return(dev->fd); } - ubd_dev->fd = fd; - if(ubd_dev->cow.file != NULL){ + if(dev->cow.file != NULL){ err = -ENOMEM; - ubd_dev->cow.bitmap = (void *) vmalloc(ubd_dev->cow.bitmap_len); - if(ubd_dev->cow.bitmap == NULL){ + dev->cow.bitmap = (void *) vmalloc(dev->cow.bitmap_len); + if(dev->cow.bitmap == NULL){ printk(KERN_ERR "Failed to vmalloc COW bitmap\n"); goto error; } flush_tlb_kernel_vm(); - err = read_cow_bitmap(ubd_dev->fd, ubd_dev->cow.bitmap, - ubd_dev->cow.bitmap_offset, - ubd_dev->cow.bitmap_len); + err = read_cow_bitmap(dev->fd, dev->cow.bitmap, + dev->cow.bitmap_offset, + dev->cow.bitmap_len); if(err < 0) goto error; - flags = ubd_dev->openflags; + flags = dev->openflags; flags.w = 0; - err = open_ubd_file(ubd_dev->cow.file, &flags, ubd_dev->shared, NULL, + err = open_ubd_file(dev->cow.file, &flags, dev->shared, NULL, NULL, NULL, NULL, NULL); if(err < 0) goto error; - ubd_dev->cow.fd = err; + dev->cow.fd = err; } return(0); error: - os_close_file(ubd_dev->fd); + os_close_file(dev->fd); return(err); } -static int ubd_disk_register(int major, u64 size, int unit, +static int ubd_new_disk(int major, u64 size, int unit, struct gendisk **disk_out) { @@ -652,13 +642,13 @@ static int ubd_disk_register(int major, u64 size, int unit, /* sysfs register (not for ide fake devices) */ if (major == MAJOR_NR) { - ubd_devs[unit].pdev.id = unit; - ubd_devs[unit].pdev.name = DRIVER_NAME; - platform_device_register(&ubd_devs[unit].pdev); - disk->driverfs_dev = &ubd_devs[unit].pdev.dev; + ubd_dev[unit].pdev.id = unit; + ubd_dev[unit].pdev.name = DRIVER_NAME; + platform_device_register(&ubd_dev[unit].pdev); + disk->driverfs_dev = &ubd_dev[unit].pdev.dev; } - disk->private_data = &ubd_devs[unit]; + disk->private_data = &ubd_dev[unit]; disk->queue = ubd_queue; add_disk(disk); @@ -670,25 +660,25 @@ static int ubd_disk_register(int major, u64 size, int unit, static int ubd_add(int n) { - struct ubd *ubd_dev = &ubd_devs[n]; + struct ubd *dev = &ubd_dev[n]; int err; err = -ENODEV; - if(ubd_dev->file == NULL) + if(dev->file == NULL) goto out; - err = ubd_file_size(ubd_dev, &ubd_dev->size); + err = ubd_file_size(dev, &dev->size); if(err < 0) goto out; - ubd_dev->size = ROUND_BLOCK(ubd_dev->size); + dev->size = ROUND_BLOCK(dev->size); - err = ubd_disk_register(MAJOR_NR, ubd_dev->size, n, &ubd_gendisk[n]); + err = ubd_new_disk(MAJOR_NR, dev->size, n, &ubd_gendisk[n]); if(err) goto out; if(fake_major != MAJOR_NR) - ubd_disk_register(fake_major, ubd_dev->size, n, + ubd_new_disk(fake_major, dev->size, n, &fake_gendisk[n]); /* perhaps this should also be under the "if (fake_major)" above */ @@ -703,41 +693,32 @@ static int ubd_add(int n) static int ubd_config(char *str) { - int n, ret; + int n, err; str = kstrdup(str, GFP_KERNEL); - if (str == NULL) { + if(str == NULL){ printk(KERN_ERR "ubd_config failed to strdup string\n"); - ret = 1; - goto out; - } - ret = ubd_setup_common(str, &n); - if (ret) { - ret = -1; - goto err_free; + return(1); } - if (n == -1) { - ret = 0; - goto err_free; + err = ubd_setup_common(str, &n); + if(err){ + kfree(str); + return(-1); } + if(n == -1) return(0); - mutex_lock(&ubd_lock); - ret = ubd_add(n); - if (ret) - ubd_devs[n].file = NULL; - mutex_unlock(&ubd_lock); - -out: - return ret; + spin_lock(&ubd_lock); + err = ubd_add(n); + if(err) + ubd_dev[n].file = NULL; + spin_unlock(&ubd_lock); -err_free: - kfree(str); - goto out; + return(err); } static int ubd_get_config(char *name, char *str, int size, char **error_out) { - struct ubd *ubd_dev; + struct ubd *dev; int n, len = 0; n = parse_unit(&name); @@ -746,24 +727,24 @@ static int ubd_get_config(char *name, char *str, int size, char **error_out) return(-1); } - ubd_dev = &ubd_devs[n]; - mutex_lock(&ubd_lock); + dev = &ubd_dev[n]; + spin_lock(&ubd_lock); - if(ubd_dev->file == NULL){ + if(dev->file == NULL){ CONFIG_CHUNK(str, size, len, "", 1); goto out; } - CONFIG_CHUNK(str, size, len, ubd_dev->file, 0); + CONFIG_CHUNK(str, size, len, dev->file, 0); - if(ubd_dev->cow.file != NULL){ + if(dev->cow.file != NULL){ CONFIG_CHUNK(str, size, len, ",", 0); - CONFIG_CHUNK(str, size, len, ubd_dev->cow.file, 1); + CONFIG_CHUNK(str, size, len, dev->cow.file, 1); } else CONFIG_CHUNK(str, size, len, "", 1); out: - mutex_unlock(&ubd_lock); + spin_unlock(&ubd_lock); return(len); } @@ -779,22 +760,22 @@ static int ubd_id(char **str, int *start_out, int *end_out) static int ubd_remove(int n) { - struct ubd *ubd_dev; + struct ubd *dev; int err = -ENODEV; - mutex_lock(&ubd_lock); + spin_lock(&ubd_lock); if(ubd_gendisk[n] == NULL) goto out; - ubd_dev = &ubd_devs[n]; + dev = &ubd_dev[n]; - if(ubd_dev->file == NULL) + if(dev->file == NULL) goto out; /* you cannot remove a open disk */ err = -EBUSY; - if(ubd_dev->count > 0) + if(dev->count > 0) goto out; del_gendisk(ubd_gendisk[n]); @@ -807,15 +788,14 @@ static int ubd_remove(int n) fake_gendisk[n] = NULL; } - platform_device_unregister(&ubd_dev->pdev); - *ubd_dev = ((struct ubd) DEFAULT_UBD); + platform_device_unregister(&dev->pdev); + *dev = ((struct ubd) DEFAULT_UBD); err = 0; out: - mutex_unlock(&ubd_lock); + spin_unlock(&ubd_lock); return err; } -/* All these are called by mconsole in process context and without ubd-specific locks. */ static struct mc_device ubd_mc = { .name = "ubd", .config = ubd_config, @@ -824,7 +804,7 @@ static struct mc_device ubd_mc = { .remove = ubd_remove, }; -static int __init ubd_mc_init(void) +static int ubd_mc_init(void) { mconsole_register_dev(&ubd_mc); return 0; @@ -832,24 +812,13 @@ static int __init ubd_mc_init(void) __initcall(ubd_mc_init); -static int __init ubd0_init(void) -{ - struct ubd *ubd_dev = &ubd_devs[0]; - - if(ubd_dev->file == NULL) - ubd_dev->file = "root_fs"; - return(0); -} - -__initcall(ubd0_init); - static struct platform_driver ubd_driver = { .driver = { .name = DRIVER_NAME, }, }; -static int __init ubd_init(void) +int ubd_init(void) { int i; @@ -877,7 +846,7 @@ static int __init ubd_init(void) late_initcall(ubd_init); -static int __init ubd_driver_init(void){ +int ubd_driver_init(void){ unsigned long stack; int err; @@ -898,7 +867,7 @@ static int __init ubd_driver_init(void){ return(0); } err = um_request_irq(UBD_IRQ, thread_fd, IRQ_READ, ubd_intr, - IRQF_DISABLED, "ubd", ubd_devs); + IRQF_DISABLED, "ubd", ubd_dev); if(err != 0) printk(KERN_ERR "um_request_irq failed - errno = %d\n", -err); return 0; @@ -909,24 +878,24 @@ device_initcall(ubd_driver_init); static int ubd_open(struct inode *inode, struct file *filp) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct ubd *ubd_dev = disk->private_data; + struct ubd *dev = disk->private_data; int err = 0; - if(ubd_dev->count == 0){ - err = ubd_open_dev(ubd_dev); + if(dev->count == 0){ + err = ubd_open_dev(dev); if(err){ printk(KERN_ERR "%s: Can't open \"%s\": errno = %d\n", - disk->disk_name, ubd_dev->file, -err); + disk->disk_name, dev->file, -err); goto out; } } - ubd_dev->count++; - set_disk_ro(disk, !ubd_dev->openflags.w); + dev->count++; + set_disk_ro(disk, !dev->openflags.w); /* This should no more be needed. And it didn't work anyway to exclude * read-write remounting of filesystems.*/ - /*if((filp->f_mode & FMODE_WRITE) && !ubd_dev->openflags.w){ - if(--ubd_dev->count == 0) ubd_close_dev(ubd_dev); + /*if((filp->f_mode & FMODE_WRITE) && !dev->openflags.w){ + if(--dev->count == 0) ubd_close(dev); err = -EROFS; }*/ out: @@ -936,10 +905,10 @@ static int ubd_open(struct inode *inode, struct file *filp) static int ubd_release(struct inode * inode, struct file * file) { struct gendisk *disk = inode->i_bdev->bd_disk; - struct ubd *ubd_dev = disk->private_data; + struct ubd *dev = disk->private_data; - if(--ubd_dev->count == 0) - ubd_close_dev(ubd_dev); + if(--dev->count == 0) + ubd_close(dev); return(0); } @@ -1007,12 +976,12 @@ static void cowify_req(struct io_thread_req *req, unsigned long *bitmap, static int prepare_request(struct request *req, struct io_thread_req *io_req) { struct gendisk *disk = req->rq_disk; - struct ubd *ubd_dev = disk->private_data; + struct ubd *dev = disk->private_data; __u64 offset; int len; /* This should be impossible now */ - if((rq_data_dir(req) == WRITE) && !ubd_dev->openflags.w){ + if((rq_data_dir(req) == WRITE) && !dev->openflags.w){ printk("Write attempted on readonly ubd device %s\n", disk->disk_name); end_request(req, 0); @@ -1022,8 +991,8 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) offset = ((__u64) req->sector) << 9; len = req->current_nr_sectors << 9; - io_req->fds[0] = (ubd_dev->cow.file != NULL) ? ubd_dev->cow.fd : ubd_dev->fd; - io_req->fds[1] = ubd_dev->fd; + io_req->fds[0] = (dev->cow.file != NULL) ? dev->cow.fd : dev->fd; + io_req->fds[1] = dev->fd; io_req->cow_offset = -1; io_req->offset = offset; io_req->length = len; @@ -1032,13 +1001,13 @@ static int prepare_request(struct request *req, struct io_thread_req *io_req) io_req->op = (rq_data_dir(req) == READ) ? UBD_READ : UBD_WRITE; io_req->offsets[0] = 0; - io_req->offsets[1] = ubd_dev->cow.data_offset; + io_req->offsets[1] = dev->cow.data_offset; io_req->buffer = req->buffer; io_req->sectorsize = 1 << 9; - if(ubd_dev->cow.file != NULL) - cowify_req(io_req, ubd_dev->cow.bitmap, ubd_dev->cow.bitmap_offset, - ubd_dev->cow.bitmap_len); + if(dev->cow.file != NULL) + cowify_req(io_req, dev->cow.bitmap, dev->cow.bitmap_offset, + dev->cow.bitmap_len); return(0); } @@ -1064,7 +1033,7 @@ static void do_ubd_request(request_queue_t *q) return; err = prepare_request(req, &io_req); if(!err){ - do_ubd = 1; + do_ubd = ubd_handler; n = os_write_file(thread_fd, (char *) &io_req, sizeof(io_req)); if(n != sizeof(io_req)) @@ -1076,18 +1045,18 @@ static void do_ubd_request(request_queue_t *q) static int ubd_getgeo(struct block_device *bdev, struct hd_geometry *geo) { - struct ubd *ubd_dev = bdev->bd_disk->private_data; + struct ubd *dev = bdev->bd_disk->private_data; geo->heads = 128; geo->sectors = 32; - geo->cylinders = ubd_dev->size / (128 * 32 * 512); + geo->cylinders = dev->size / (128 * 32 * 512); return 0; } static int ubd_ioctl(struct inode * inode, struct file * file, unsigned int cmd, unsigned long arg) { - struct ubd *ubd_dev = inode->i_bdev->bd_disk->private_data; + struct ubd *dev = inode->i_bdev->bd_disk->private_data; struct hd_driveid ubd_id = { .cyls = 0, .heads = 128, @@ -1097,7 +1066,7 @@ static int ubd_ioctl(struct inode * inode, struct file * file, switch (cmd) { struct cdrom_volctrl volume; case HDIO_GET_IDENTITY: - ubd_id.cyls = ubd_dev->size / (128 * 32 * 512); + ubd_id.cyls = dev->size / (128 * 32 * 512); if(copy_to_user((char __user *) arg, (char *) &ubd_id, sizeof(ubd_id))) return(-EFAULT); @@ -1384,8 +1353,8 @@ void do_io(struct io_thread_req *req) */ int kernel_fd = -1; -/* Only changed by the io thread. XXX: currently unused. */ -static int io_count = 0; +/* Only changed by the io thread */ +int io_count = 0; int io_thread(void *arg) { diff --git a/trunk/arch/um/include/mconsole_kern.h b/trunk/arch/um/include/mconsole_kern.h index 1ea6d928e1cd..d0b690197fd7 100644 --- a/trunk/arch/um/include/mconsole_kern.h +++ b/trunk/arch/um/include/mconsole_kern.h @@ -14,7 +14,6 @@ struct mconsole_entry { struct mc_request request; }; -/* All these methods are called in process context. */ struct mc_device { struct list_head list; char *name; diff --git a/trunk/arch/um/kernel/dyn.lds.S b/trunk/arch/um/kernel/dyn.lds.S index e36f92b463ce..68ed24df5c8f 100644 --- a/trunk/arch/um/kernel/dyn.lds.S +++ b/trunk/arch/um/kernel/dyn.lds.S @@ -14,7 +14,6 @@ SECTIONS * is remapped.*/ __binary_start = .; . = ALIGN(4096); /* Init code and data */ - _text = .; _stext = .; __init_begin = .; .init.text : { diff --git a/trunk/arch/um/kernel/tt/tracer.c b/trunk/arch/um/kernel/tt/tracer.c index b9195355075a..9882342206ec 100644 --- a/trunk/arch/um/kernel/tt/tracer.c +++ b/trunk/arch/um/kernel/tt/tracer.c @@ -176,6 +176,7 @@ struct { int signal_index[32]; int nsignals = 0; int debug_trace = 0; +extern int io_nsignals, io_count, intr_count; extern void signal_usr1(int sig); diff --git a/trunk/arch/um/kernel/uml.lds.S b/trunk/arch/um/kernel/uml.lds.S index f6301274cf3c..8eca47a6ff08 100644 --- a/trunk/arch/um/kernel/uml.lds.S +++ b/trunk/arch/um/kernel/uml.lds.S @@ -25,7 +25,6 @@ SECTIONS . = ALIGN(4096); /* Init code and data */ #endif - _text = .; _stext = .; __init_begin = .; .init.text : { diff --git a/trunk/block/ll_rw_blk.c b/trunk/block/ll_rw_blk.c index c7b1dac8bee9..136066583c68 100644 --- a/trunk/block/ll_rw_blk.c +++ b/trunk/block/ll_rw_blk.c @@ -2999,7 +2999,6 @@ void generic_make_request(struct bio *bio) { request_queue_t *q; sector_t maxsector; - sector_t old_sector; int ret, nr_sectors = bio_sectors(bio); dev_t old_dev; @@ -3028,7 +3027,7 @@ void generic_make_request(struct bio *bio) * NOTE: we don't repeat the blk_size check for each new device. * Stacking drivers are expected to know what they are doing. */ - old_sector = -1; + maxsector = -1; old_dev = 0; do { char b[BDEVNAME_SIZE]; @@ -3062,30 +3061,15 @@ void generic_make_request(struct bio *bio) */ blk_partition_remap(bio); - if (old_sector != -1) + if (maxsector != -1) blk_add_trace_remap(q, bio, old_dev, bio->bi_sector, - old_sector); + maxsector); blk_add_trace_bio(q, bio, BLK_TA_QUEUE); - old_sector = bio->bi_sector; + maxsector = bio->bi_sector; old_dev = bio->bi_bdev->bd_dev; - maxsector = bio->bi_bdev->bd_inode->i_size >> 9; - if (maxsector) { - sector_t sector = bio->bi_sector; - - if (maxsector < nr_sectors || maxsector - nr_sectors < sector) { - /* - * This may well happen - partitions are not checked - * to make sure they are within the size of the - * whole device. - */ - handle_bad_sector(bio); - goto end_io; - } - } - ret = q->make_request_fn(q, bio); } while (ret); } diff --git a/trunk/drivers/ieee1394/eth1394.c b/trunk/drivers/ieee1394/eth1394.c index 31e5cc49d61a..8a7b8fab6238 100644 --- a/trunk/drivers/ieee1394/eth1394.c +++ b/trunk/drivers/ieee1394/eth1394.c @@ -64,7 +64,6 @@ #include #include #include -#include #include #include "config_roms.h" @@ -492,7 +491,7 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu) int i; struct eth1394_priv *priv = netdev_priv(dev); struct hpsb_host *host = priv->host; - u64 guid = get_unaligned((u64*)&(host->csr.rom->bus_info_data[3])); + u64 guid = *((u64*)&(host->csr.rom->bus_info_data[3])); u16 maxpayload = 1 << (host->csr.max_rec + 1); int max_speed = IEEE1394_SPEED_MAX; @@ -515,8 +514,8 @@ static void ether1394_reset_priv (struct net_device *dev, int set_mtu) ETHER1394_GASP_OVERHEAD))); /* Set our hardware address while we're at it */ - memcpy(dev->dev_addr, &guid, sizeof(u64)); - memset(dev->broadcast, 0xff, sizeof(u64)); + *(u64*)dev->dev_addr = guid; + *(u64*)dev->broadcast = ~0x0ULL; } spin_unlock_irqrestore (&priv->lock, flags); @@ -895,7 +894,6 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, u16 maxpayload; struct eth1394_node_ref *node; struct eth1394_node_info *node_info; - __be64 guid; /* Sanity check. MacOSX seems to be sending us 131 in this * field (atleast on my Panther G5). Not sure why. */ @@ -904,9 +902,8 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, maxpayload = min(eth1394_speedto_maxpayload[sspd], (u16)(1 << (max_rec + 1))); - guid = get_unaligned(&arp1394->s_uniq_id); node = eth1394_find_node_guid(&priv->ip_node_list, - be64_to_cpu(guid)); + be64_to_cpu(arp1394->s_uniq_id)); if (!node) { return 0; } @@ -934,9 +931,10 @@ static inline u16 ether1394_parse_encap(struct sk_buff *skb, arp_ptr += arp->ar_pln; /* skip over sender IP addr */ if (arp->ar_op == htons(ARPOP_REQUEST)) - memset(arp_ptr, 0, sizeof(u64)); + /* just set ARP req target unique ID to 0 */ + *((u64*)arp_ptr) = 0; else - memcpy(arp_ptr, dev->dev_addr, sizeof(u64)); + *((u64*)arp_ptr) = *((u64*)dev->dev_addr); } /* Now add the ethernet header. */ @@ -1677,10 +1675,8 @@ static int ether1394_tx (struct sk_buff *skb, struct net_device *dev) if (max_payload < dg_size + hdr_type_len[ETH1394_HDR_LF_UF]) priv->bc_dgl++; } else { - __be64 guid = get_unaligned((u64 *)eth->h_dest); - node = eth1394_find_node_guid(&priv->ip_node_list, - be64_to_cpu(guid)); + be64_to_cpu(*(u64*)eth->h_dest)); if (!node) { ret = -EAGAIN; goto fail; diff --git a/trunk/drivers/net/wan/Kconfig b/trunk/drivers/net/wan/Kconfig index b5d0d7fb647a..58b7efbb0750 100644 --- a/trunk/drivers/net/wan/Kconfig +++ b/trunk/drivers/net/wan/Kconfig @@ -127,7 +127,7 @@ config LANMEDIA # There is no way to detect a Sealevel board. Force it modular config SEALEVEL_4021 tristate "Sealevel Systems 4021 support" - depends on WAN && ISA && m && ISA_DMA_API && INET + depends on WAN && ISA && m && ISA_DMA_API help This is a driver for the Sealevel Systems ACB 56 serial I/O adapter. diff --git a/trunk/fs/block_dev.c b/trunk/fs/block_dev.c index 36c0e7af9d0f..aaa8301f43f1 100644 --- a/trunk/fs/block_dev.c +++ b/trunk/fs/block_dev.c @@ -651,8 +651,7 @@ static void free_bd_holder(struct bd_holder *bo) * If found, increment the reference count and return the pointer. * If not found, returns NULL. */ -static struct bd_holder *find_bd_holder(struct block_device *bdev, - struct bd_holder *bo) +static int find_bd_holder(struct block_device *bdev, struct bd_holder *bo) { struct bd_holder *tmp; @@ -678,6 +677,7 @@ static struct bd_holder *find_bd_holder(struct block_device *bdev, */ static int add_bd_holder(struct block_device *bdev, struct bd_holder *bo) { + struct bd_holder *tmp; int ret; if (!bo) diff --git a/trunk/fs/ecryptfs/crypto.c b/trunk/fs/ecryptfs/crypto.c index f49f105394b7..ed35a9712fa1 100644 --- a/trunk/fs/ecryptfs/crypto.c +++ b/trunk/fs/ecryptfs/crypto.c @@ -94,53 +94,25 @@ static int ecryptfs_calculate_md5(char *dst, struct ecryptfs_crypt_stat *crypt_stat, char *src, int len) { - struct scatterlist sg; - struct hash_desc desc = { - .tfm = crypt_stat->hash_tfm, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; int rc = 0; + struct scatterlist sg; - mutex_lock(&crypt_stat->cs_hash_tfm_mutex); + mutex_lock(&crypt_stat->cs_md5_tfm_mutex); sg_init_one(&sg, (u8 *)src, len); - if (!desc.tfm) { - desc.tfm = crypto_alloc_hash(ECRYPTFS_DEFAULT_HASH, 0, - CRYPTO_ALG_ASYNC); - if (IS_ERR(desc.tfm)) { - rc = PTR_ERR(desc.tfm); + if (!crypt_stat->md5_tfm) { + crypt_stat->md5_tfm = + crypto_alloc_tfm("md5", CRYPTO_TFM_REQ_MAY_SLEEP); + if (!crypt_stat->md5_tfm) { + rc = -ENOMEM; ecryptfs_printk(KERN_ERR, "Error attempting to " - "allocate crypto context; rc = [%d]\n", - rc); + "allocate crypto context\n"); goto out; } - crypt_stat->hash_tfm = desc.tfm; } - crypto_hash_init(&desc); - crypto_hash_update(&desc, &sg, len); - crypto_hash_final(&desc, dst); - mutex_unlock(&crypt_stat->cs_hash_tfm_mutex); -out: - return rc; -} - -int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, - char *cipher_name, - char *chaining_modifier) -{ - int cipher_name_len = strlen(cipher_name); - int chaining_modifier_len = strlen(chaining_modifier); - int algified_name_len; - int rc; - - algified_name_len = (chaining_modifier_len + cipher_name_len + 3); - (*algified_name) = kmalloc(algified_name_len, GFP_KERNEL); - if (!(algified_name)) { - rc = -ENOMEM; - goto out; - } - snprintf((*algified_name), algified_name_len, "%s(%s)", - chaining_modifier, cipher_name); - rc = 0; + crypto_digest_init(crypt_stat->md5_tfm); + crypto_digest_update(crypt_stat->md5_tfm, &sg, 1); + crypto_digest_final(crypt_stat->md5_tfm, dst); + mutex_unlock(&crypt_stat->cs_md5_tfm_mutex); out: return rc; } @@ -206,7 +178,7 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) memset((void *)crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); mutex_init(&crypt_stat->cs_mutex); mutex_init(&crypt_stat->cs_tfm_mutex); - mutex_init(&crypt_stat->cs_hash_tfm_mutex); + mutex_init(&crypt_stat->cs_md5_tfm_mutex); ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_STRUCT_INITIALIZED); } @@ -219,9 +191,9 @@ ecryptfs_init_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat) { if (crypt_stat->tfm) - crypto_free_blkcipher(crypt_stat->tfm); - if (crypt_stat->hash_tfm) - crypto_free_hash(crypt_stat->hash_tfm); + crypto_free_tfm(crypt_stat->tfm); + if (crypt_stat->md5_tfm) + crypto_free_tfm(crypt_stat->md5_tfm); memset(crypt_stat, 0, sizeof(struct ecryptfs_crypt_stat)); } @@ -231,7 +203,7 @@ void ecryptfs_destruct_mount_crypt_stat( if (mount_crypt_stat->global_auth_tok_key) key_put(mount_crypt_stat->global_auth_tok_key); if (mount_crypt_stat->global_key_tfm) - crypto_free_blkcipher(mount_crypt_stat->global_key_tfm); + crypto_free_tfm(mount_crypt_stat->global_key_tfm); memset(mount_crypt_stat, 0, sizeof(struct ecryptfs_mount_crypt_stat)); } @@ -297,11 +269,6 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, struct scatterlist *src_sg, int size, unsigned char *iv) { - struct blkcipher_desc desc = { - .tfm = crypt_stat->tfm, - .info = iv, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; int rc = 0; BUG_ON(!crypt_stat || !crypt_stat->tfm @@ -315,8 +282,8 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, } /* Consider doing this once, when the file is opened */ mutex_lock(&crypt_stat->cs_tfm_mutex); - rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, - crypt_stat->key_size); + rc = crypto_cipher_setkey(crypt_stat->tfm, crypt_stat->key, + crypt_stat->key_size); if (rc) { ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", rc); @@ -325,7 +292,7 @@ static int encrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, goto out; } ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes.\n", size); - crypto_blkcipher_encrypt_iv(&desc, dest_sg, src_sg, size); + crypto_cipher_encrypt_iv(crypt_stat->tfm, dest_sg, src_sg, size, iv); mutex_unlock(&crypt_stat->cs_tfm_mutex); out: return rc; @@ -708,17 +675,12 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, struct scatterlist *src_sg, int size, unsigned char *iv) { - struct blkcipher_desc desc = { - .tfm = crypt_stat->tfm, - .info = iv, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; int rc = 0; /* Consider doing this once, when the file is opened */ mutex_lock(&crypt_stat->cs_tfm_mutex); - rc = crypto_blkcipher_setkey(crypt_stat->tfm, crypt_stat->key, - crypt_stat->key_size); + rc = crypto_cipher_setkey(crypt_stat->tfm, crypt_stat->key, + crypt_stat->key_size); if (rc) { ecryptfs_printk(KERN_ERR, "Error setting key; rc = [%d]\n", rc); @@ -727,7 +689,8 @@ static int decrypt_scatterlist(struct ecryptfs_crypt_stat *crypt_stat, goto out; } ecryptfs_printk(KERN_DEBUG, "Decrypting [%d] bytes.\n", size); - rc = crypto_blkcipher_decrypt_iv(&desc, dest_sg, src_sg, size); + rc = crypto_cipher_decrypt_iv(crypt_stat->tfm, dest_sg, src_sg, size, + iv); mutex_unlock(&crypt_stat->cs_tfm_mutex); if (rc) { ecryptfs_printk(KERN_ERR, "Error decrypting; rc = [%d]\n", @@ -796,7 +759,6 @@ ecryptfs_decrypt_page_offset(struct ecryptfs_crypt_stat *crypt_stat, */ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) { - char *full_alg_name; int rc = -EINVAL; if (!crypt_stat->cipher) { @@ -813,24 +775,16 @@ int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat) goto out; } mutex_lock(&crypt_stat->cs_tfm_mutex); - rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, - crypt_stat->cipher, "cbc"); - if (rc) - goto out; - crypt_stat->tfm = crypto_alloc_blkcipher(full_alg_name, 0, - CRYPTO_ALG_ASYNC); - kfree(full_alg_name); + crypt_stat->tfm = crypto_alloc_tfm(crypt_stat->cipher, + ECRYPTFS_DEFAULT_CHAINING_MODE + | CRYPTO_TFM_REQ_WEAK_KEY); + mutex_unlock(&crypt_stat->cs_tfm_mutex); if (!crypt_stat->tfm) { ecryptfs_printk(KERN_ERR, "cryptfs: init_crypt_ctx(): " "Error initializing cipher [%s]\n", crypt_stat->cipher); - mutex_unlock(&crypt_stat->cs_tfm_mutex); goto out; } - crypto_blkcipher_set_flags(crypt_stat->tfm, - (ECRYPTFS_DEFAULT_CHAINING_MODE - | CRYPTO_TFM_REQ_WEAK_KEY)); - mutex_unlock(&crypt_stat->cs_tfm_mutex); rc = 0; out: return rc; @@ -1191,28 +1145,28 @@ int ecryptfs_cipher_code_to_string(char *str, u16 cipher_code) int ecryptfs_read_header_region(char *data, struct dentry *dentry, struct vfsmount *mnt) { - struct file *lower_file; + struct file *file; mm_segment_t oldfs; int rc; - if ((rc = ecryptfs_open_lower_file(&lower_file, dentry, mnt, - O_RDONLY))) { - printk(KERN_ERR - "Error opening lower_file to read header region\n"); + mnt = mntget(mnt); + file = dentry_open(dentry, mnt, O_RDONLY); + if (IS_ERR(file)) { + ecryptfs_printk(KERN_DEBUG, "Error opening file to " + "read header region\n"); + mntput(mnt); + rc = PTR_ERR(file); goto out; } - lower_file->f_pos = 0; + file->f_pos = 0; oldfs = get_fs(); set_fs(get_ds()); /* For releases 0.1 and 0.2, all of the header information * fits in the first data extent-sized region. */ - rc = lower_file->f_op->read(lower_file, (char __user *)data, - ECRYPTFS_DEFAULT_EXTENT_SIZE, &lower_file->f_pos); + rc = file->f_op->read(file, (char __user *)data, + ECRYPTFS_DEFAULT_EXTENT_SIZE, &file->f_pos); set_fs(oldfs); - if ((rc = ecryptfs_close_lower_file(lower_file))) { - printk(KERN_ERR "Error closing lower_file\n"); - goto out; - } + fput(file); rc = 0; out: return rc; @@ -1619,52 +1573,84 @@ ecryptfs_decode_filename(struct ecryptfs_crypt_stat *crypt_stat, /** * ecryptfs_process_cipher - Perform cipher initialization. + * @tfm: Crypto context set by this function * @key_tfm: Crypto context for key material, set by this function - * @cipher_name: Name of the cipher - * @key_size: Size of the key in bytes + * @cipher_name: Name of the cipher. + * @key_size: Size of the key in bytes. * * Returns zero on success. Any crypto_tfm structs allocated here * should be released by other functions, such as on a superblock put * event, regardless of whether this function succeeds for fails. */ int -ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, - size_t *key_size) +ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm, + char *cipher_name, size_t key_size) { char dummy_key[ECRYPTFS_MAX_KEY_BYTES]; - char *full_alg_name; int rc; - *key_tfm = NULL; - if (*key_size > ECRYPTFS_MAX_KEY_BYTES) { + *tfm = *key_tfm = NULL; + if (key_size > ECRYPTFS_MAX_KEY_BYTES) { rc = -EINVAL; printk(KERN_ERR "Requested key size is [%Zd] bytes; maximum " - "allowable is [%d]\n", *key_size, ECRYPTFS_MAX_KEY_BYTES); + "allowable is [%d]\n", key_size, ECRYPTFS_MAX_KEY_BYTES); goto out; } - rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, cipher_name, - "ecb"); - if (rc) + *tfm = crypto_alloc_tfm(cipher_name, (ECRYPTFS_DEFAULT_CHAINING_MODE + | CRYPTO_TFM_REQ_WEAK_KEY)); + if (!(*tfm)) { + rc = -EINVAL; + printk(KERN_ERR "Unable to allocate crypto cipher with name " + "[%s]\n", cipher_name); goto out; - *key_tfm = crypto_alloc_blkcipher(full_alg_name, 0, CRYPTO_ALG_ASYNC); - kfree(full_alg_name); - if (IS_ERR(*key_tfm)) { - rc = PTR_ERR(*key_tfm); + } + *key_tfm = crypto_alloc_tfm(cipher_name, CRYPTO_TFM_REQ_WEAK_KEY); + if (!(*key_tfm)) { + rc = -EINVAL; printk(KERN_ERR "Unable to allocate crypto cipher with name " - "[%s]; rc = [%d]\n", cipher_name, rc); + "[%s]\n", cipher_name); goto out; } - crypto_blkcipher_set_flags(*key_tfm, CRYPTO_TFM_REQ_WEAK_KEY); - if (*key_size == 0) { - struct blkcipher_alg *alg = crypto_blkcipher_alg(*key_tfm); - - *key_size = alg->max_keysize; + if (key_size < crypto_tfm_alg_min_keysize(*tfm)) { + rc = -EINVAL; + printk(KERN_ERR "Request key size is [%Zd]; minimum key size " + "supported by cipher [%s] is [%d]\n", key_size, + cipher_name, crypto_tfm_alg_min_keysize(*tfm)); + goto out; + } + if (key_size < crypto_tfm_alg_min_keysize(*key_tfm)) { + rc = -EINVAL; + printk(KERN_ERR "Request key size is [%Zd]; minimum key size " + "supported by cipher [%s] is [%d]\n", key_size, + cipher_name, crypto_tfm_alg_min_keysize(*key_tfm)); + goto out; + } + if (key_size > crypto_tfm_alg_max_keysize(*tfm)) { + rc = -EINVAL; + printk(KERN_ERR "Request key size is [%Zd]; maximum key size " + "supported by cipher [%s] is [%d]\n", key_size, + cipher_name, crypto_tfm_alg_min_keysize(*tfm)); + goto out; + } + if (key_size > crypto_tfm_alg_max_keysize(*key_tfm)) { + rc = -EINVAL; + printk(KERN_ERR "Request key size is [%Zd]; maximum key size " + "supported by cipher [%s] is [%d]\n", key_size, + cipher_name, crypto_tfm_alg_min_keysize(*key_tfm)); + goto out; + } + get_random_bytes(dummy_key, key_size); + rc = crypto_cipher_setkey(*tfm, dummy_key, key_size); + if (rc) { + printk(KERN_ERR "Error attempting to set key of size [%Zd] for " + "cipher [%s]; rc = [%d]\n", key_size, cipher_name, rc); + rc = -EINVAL; + goto out; } - get_random_bytes(dummy_key, *key_size); - rc = crypto_blkcipher_setkey(*key_tfm, dummy_key, *key_size); + rc = crypto_cipher_setkey(*key_tfm, dummy_key, key_size); if (rc) { printk(KERN_ERR "Error attempting to set key of size [%Zd] for " - "cipher [%s]; rc = [%d]\n", *key_size, cipher_name, rc); + "cipher [%s]; rc = [%d]\n", key_size, cipher_name, rc); rc = -EINVAL; goto out; } diff --git a/trunk/fs/ecryptfs/dentry.c b/trunk/fs/ecryptfs/dentry.c index 0b9992ab990f..f0d2a433242b 100644 --- a/trunk/fs/ecryptfs/dentry.c +++ b/trunk/fs/ecryptfs/dentry.c @@ -24,7 +24,6 @@ #include #include -#include #include "ecryptfs_kernel.h" /** @@ -77,13 +76,8 @@ static void ecryptfs_d_release(struct dentry *dentry) if (ecryptfs_dentry_to_private(dentry)) kmem_cache_free(ecryptfs_dentry_info_cache, ecryptfs_dentry_to_private(dentry)); - if (lower_dentry) { - struct vfsmount *lower_mnt = - ecryptfs_dentry_to_lower_mnt(dentry); - - mntput(lower_mnt); + if (lower_dentry) dput(lower_dentry); - } return; } diff --git a/trunk/fs/ecryptfs/ecryptfs_kernel.h b/trunk/fs/ecryptfs/ecryptfs_kernel.h index f992533d1692..872c9958531a 100644 --- a/trunk/fs/ecryptfs/ecryptfs_kernel.h +++ b/trunk/fs/ecryptfs/ecryptfs_kernel.h @@ -175,7 +175,6 @@ ecryptfs_get_key_payload_data(struct key *key) #define ECRYPTFS_DEFAULT_CIPHER "aes" #define ECRYPTFS_DEFAULT_KEY_BYTES 16 #define ECRYPTFS_DEFAULT_CHAINING_MODE CRYPTO_TFM_MODE_CBC -#define ECRYPTFS_DEFAULT_HASH "md5" #define ECRYPTFS_TAG_3_PACKET_TYPE 0x8C #define ECRYPTFS_TAG_11_PACKET_TYPE 0xED #define MD5_DIGEST_SIZE 16 @@ -205,15 +204,15 @@ struct ecryptfs_crypt_stat { size_t extent_shift; unsigned int extent_mask; struct ecryptfs_mount_crypt_stat *mount_crypt_stat; - struct crypto_blkcipher *tfm; - struct crypto_hash *hash_tfm; /* Crypto context for generating - * the initialization vectors */ + struct crypto_tfm *tfm; + struct crypto_tfm *md5_tfm; /* Crypto context for generating + * the initialization vectors */ unsigned char cipher[ECRYPTFS_MAX_CIPHER_NAME_SIZE]; unsigned char key[ECRYPTFS_MAX_KEY_BYTES]; unsigned char root_iv[ECRYPTFS_MAX_IV_BYTES]; unsigned char keysigs[ECRYPTFS_MAX_NUM_KEYSIGS][ECRYPTFS_SIG_SIZE_HEX]; struct mutex cs_tfm_mutex; - struct mutex cs_hash_tfm_mutex; + struct mutex cs_md5_tfm_mutex; struct mutex cs_mutex; }; @@ -245,7 +244,7 @@ struct ecryptfs_mount_crypt_stat { struct ecryptfs_auth_tok *global_auth_tok; struct key *global_auth_tok_key; size_t global_default_cipher_key_size; - struct crypto_blkcipher *global_key_tfm; + struct crypto_tfm *global_key_tfm; struct mutex global_key_tfm_mutex; unsigned char global_default_cipher_name[ECRYPTFS_MAX_CIPHER_NAME_SIZE + 1]; @@ -426,9 +425,6 @@ void ecryptfs_destruct_crypt_stat(struct ecryptfs_crypt_stat *crypt_stat); void ecryptfs_destruct_mount_crypt_stat( struct ecryptfs_mount_crypt_stat *mount_crypt_stat); int ecryptfs_init_crypt_ctx(struct ecryptfs_crypt_stat *crypt_stat); -int ecryptfs_crypto_api_algify_cipher_name(char **algified_name, - char *cipher_name, - char *chaining_modifier); int ecryptfs_write_inode_size_to_header(struct file *lower_file, struct inode *lower_inode, struct inode *inode); @@ -477,14 +473,10 @@ ecryptfs_parse_packet_set(struct ecryptfs_crypt_stat *crypt_stat, unsigned char *src, struct dentry *ecryptfs_dentry); int ecryptfs_truncate(struct dentry *dentry, loff_t new_length); int -ecryptfs_process_cipher(struct crypto_blkcipher **key_tfm, char *cipher_name, - size_t *key_size); +ecryptfs_process_cipher(struct crypto_tfm **tfm, struct crypto_tfm **key_tfm, + char *cipher_name, size_t key_size); int ecryptfs_inode_test(struct inode *inode, void *candidate_lower_inode); int ecryptfs_inode_set(struct inode *inode, void *lower_inode); void ecryptfs_init_inode(struct inode *inode, struct inode *lower_inode); -int ecryptfs_open_lower_file(struct file **lower_file, - struct dentry *lower_dentry, - struct vfsmount *lower_mnt, int flags); -int ecryptfs_close_lower_file(struct file *lower_file); #endif /* #ifndef ECRYPTFS_KERNEL_H */ diff --git a/trunk/fs/ecryptfs/file.c b/trunk/fs/ecryptfs/file.c index a92ef05eff8f..c8550c9f9cd2 100644 --- a/trunk/fs/ecryptfs/file.c +++ b/trunk/fs/ecryptfs/file.c @@ -198,33 +198,6 @@ static int ecryptfs_readdir(struct file *file, void *dirent, filldir_t filldir) struct kmem_cache *ecryptfs_file_info_cache; -int ecryptfs_open_lower_file(struct file **lower_file, - struct dentry *lower_dentry, - struct vfsmount *lower_mnt, int flags) -{ - int rc = 0; - - dget(lower_dentry); - mntget(lower_mnt); - *lower_file = dentry_open(lower_dentry, lower_mnt, flags); - if (IS_ERR(*lower_file)) { - printk(KERN_ERR "Error opening lower file for lower_dentry " - "[0x%p], lower_mnt [0x%p], and flags [0x%x]\n", - lower_dentry, lower_mnt, flags); - rc = PTR_ERR(*lower_file); - *lower_file = NULL; - goto out; - } -out: - return rc; -} - -int ecryptfs_close_lower_file(struct file *lower_file) -{ - fput(lower_file); - return 0; -} - /** * ecryptfs_open * @inode: inode speciying file to open @@ -271,15 +244,19 @@ static int ecryptfs_open(struct inode *inode, struct file *file) ECRYPTFS_SET_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); } mutex_unlock(&crypt_stat->cs_mutex); + /* This mntget & dget is undone via fput when the file is released */ + dget(lower_dentry); lower_flags = file->f_flags; if ((lower_flags & O_ACCMODE) == O_WRONLY) lower_flags = (lower_flags & O_ACCMODE) | O_RDWR; if (file->f_flags & O_APPEND) lower_flags &= ~O_APPEND; lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); + mntget(lower_mnt); /* Corresponding fput() in ecryptfs_release() */ - if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, - lower_flags))) { + lower_file = dentry_open(lower_dentry, lower_mnt, lower_flags); + if (IS_ERR(lower_file)) { + rc = PTR_ERR(lower_file); ecryptfs_printk(KERN_ERR, "Error opening lower file\n"); goto out_puts; } @@ -364,16 +341,11 @@ static int ecryptfs_release(struct inode *inode, struct file *file) struct file *lower_file = ecryptfs_file_to_lower(file); struct ecryptfs_file_info *file_info = ecryptfs_file_to_private(file); struct inode *lower_inode = ecryptfs_inode_to_lower(inode); - int rc; - if ((rc = ecryptfs_close_lower_file(lower_file))) { - printk(KERN_ERR "Error closing lower_file\n"); - goto out; - } + fput(lower_file); inode->i_blocks = lower_inode->i_blocks; kmem_cache_free(ecryptfs_file_info_cache, file_info); -out: - return rc; + return 0; } static int diff --git a/trunk/fs/ecryptfs/inode.c b/trunk/fs/ecryptfs/inode.c index ff4865d24f0f..efdd2b7b62d7 100644 --- a/trunk/fs/ecryptfs/inode.c +++ b/trunk/fs/ecryptfs/inode.c @@ -231,6 +231,7 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) int lower_flags; struct ecryptfs_crypt_stat *crypt_stat; struct dentry *lower_dentry; + struct dentry *tlower_dentry = NULL; struct file *lower_file; struct inode *inode, *lower_inode; struct vfsmount *lower_mnt; @@ -240,19 +241,30 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) lower_dentry->d_name.name); inode = ecryptfs_dentry->d_inode; crypt_stat = &ecryptfs_inode_to_private(inode)->crypt_stat; + tlower_dentry = dget(lower_dentry); + if (!tlower_dentry) { + rc = -ENOMEM; + ecryptfs_printk(KERN_ERR, "Error dget'ing lower_dentry\n"); + goto out; + } lower_flags = ((O_CREAT | O_WRONLY | O_TRUNC) & O_ACCMODE) | O_RDWR; #if BITS_PER_LONG != 32 lower_flags |= O_LARGEFILE; #endif lower_mnt = ecryptfs_dentry_to_lower_mnt(ecryptfs_dentry); + mntget(lower_mnt); /* Corresponding fput() at end of this function */ - if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, - lower_flags))) { + lower_file = dentry_open(tlower_dentry, lower_mnt, lower_flags); + if (IS_ERR(lower_file)) { + rc = PTR_ERR(lower_file); ecryptfs_printk(KERN_ERR, "Error opening dentry; rc = [%i]\n", rc); goto out; } - lower_inode = lower_dentry->d_inode; + /* fput(lower_file) should handle the puts if we do this */ + lower_file->f_dentry = tlower_dentry; + lower_file->f_vfsmnt = lower_mnt; + lower_inode = tlower_dentry->d_inode; if (S_ISDIR(ecryptfs_dentry->d_inode->i_mode)) { ecryptfs_printk(KERN_DEBUG, "This is a directory\n"); ECRYPTFS_CLEAR_FLAG(crypt_stat->flags, ECRYPTFS_ENCRYPTED); @@ -273,8 +285,7 @@ static int ecryptfs_initialize_file(struct dentry *ecryptfs_dentry) } rc = grow_file(ecryptfs_dentry, lower_file, inode, lower_inode); out_fput: - if ((rc = ecryptfs_close_lower_file(lower_file))) - printk(KERN_ERR "Error closing lower_file\n"); + fput(lower_file); out: return rc; } @@ -325,6 +336,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, struct dentry *lower_dir_dentry; struct dentry *lower_dentry; struct vfsmount *lower_mnt; + struct dentry *tlower_dentry = NULL; char *encoded_name; unsigned int encoded_namelen; struct ecryptfs_crypt_stat *crypt_stat = NULL; @@ -335,32 +347,27 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, lower_dir_dentry = ecryptfs_dentry_to_lower(dentry->d_parent); dentry->d_op = &ecryptfs_dops; if ((dentry->d_name.len == 1 && !strcmp(dentry->d_name.name, ".")) - || (dentry->d_name.len == 2 - && !strcmp(dentry->d_name.name, ".."))) { - d_drop(dentry); - goto out; - } + || (dentry->d_name.len == 2 && !strcmp(dentry->d_name.name, ".."))) + goto out_drop; encoded_namelen = ecryptfs_encode_filename(crypt_stat, dentry->d_name.name, dentry->d_name.len, &encoded_name); if (encoded_namelen < 0) { rc = encoded_namelen; - d_drop(dentry); - goto out; + goto out_drop; } ecryptfs_printk(KERN_DEBUG, "encoded_name = [%s]; encoded_namelen " "= [%d]\n", encoded_name, encoded_namelen); lower_dentry = lookup_one_len(encoded_name, lower_dir_dentry, encoded_namelen - 1); kfree(encoded_name); + lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); if (IS_ERR(lower_dentry)) { ecryptfs_printk(KERN_ERR, "ERR from lower_dentry\n"); rc = PTR_ERR(lower_dentry); - d_drop(dentry); - goto out; + goto out_drop; } - lower_mnt = mntget(ecryptfs_dentry_to_lower_mnt(dentry->d_parent)); ecryptfs_printk(KERN_DEBUG, "lower_dentry = [%p]; lower_dentry->" "d_name.name = [%s]\n", lower_dentry, lower_dentry->d_name.name); @@ -401,6 +408,12 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, "as we *think* we are about to unlink\n"); goto out; } + tlower_dentry = dget(lower_dentry); + if (!tlower_dentry || IS_ERR(tlower_dentry)) { + rc = -ENOMEM; + ecryptfs_printk(KERN_ERR, "Cannot dget lower_dentry\n"); + goto out_dput; + } /* Released in this function */ page_virt = (char *)kmem_cache_alloc(ecryptfs_header_cache_2, @@ -412,7 +425,7 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, goto out_dput; } memset(page_virt, 0, PAGE_CACHE_SIZE); - rc = ecryptfs_read_header_region(page_virt, lower_dentry, nd->mnt); + rc = ecryptfs_read_header_region(page_virt, tlower_dentry, nd->mnt); crypt_stat = &ecryptfs_inode_to_private(dentry->d_inode)->crypt_stat; if (!ECRYPTFS_CHECK_FLAG(crypt_stat->flags, ECRYPTFS_POLICY_APPLIED)) ecryptfs_set_default_sizes(crypt_stat); @@ -435,6 +448,9 @@ static struct dentry *ecryptfs_lookup(struct inode *dir, struct dentry *dentry, out_dput: dput(lower_dentry); + if (tlower_dentry) + dput(tlower_dentry); +out_drop: d_drop(dentry); out: return ERR_PTR(rc); @@ -470,8 +486,8 @@ static int ecryptfs_link(struct dentry *old_dentry, struct inode *dir, unlock_dir(lower_dir_dentry); dput(lower_new_dentry); dput(lower_old_dentry); - d_drop(new_dentry); - d_drop(old_dentry); + if (!new_dentry->d_inode) + d_drop(new_dentry); return rc; } @@ -560,24 +576,41 @@ static int ecryptfs_mkdir(struct inode *dir, struct dentry *dentry, int mode) static int ecryptfs_rmdir(struct inode *dir, struct dentry *dentry) { + int rc = 0; + struct dentry *tdentry = NULL; struct dentry *lower_dentry; + struct dentry *tlower_dentry = NULL; struct dentry *lower_dir_dentry; - int rc; lower_dentry = ecryptfs_dentry_to_lower(dentry); - dget(dentry); + if (!(tdentry = dget(dentry))) { + rc = -EINVAL; + ecryptfs_printk(KERN_ERR, "Error dget'ing dentry [%p]\n", + dentry); + goto out; + } lower_dir_dentry = lock_parent(lower_dentry); - dget(lower_dentry); + if (!(tlower_dentry = dget(lower_dentry))) { + rc = -EINVAL; + ecryptfs_printk(KERN_ERR, "Error dget'ing lower_dentry " + "[%p]\n", lower_dentry); + goto out; + } rc = vfs_rmdir(lower_dir_dentry->d_inode, lower_dentry); - dput(lower_dentry); - if (!rc) - d_delete(lower_dentry); + if (!rc) { + d_delete(tlower_dentry); + tlower_dentry = NULL; + } ecryptfs_copy_attr_times(dir, lower_dir_dentry->d_inode); dir->i_nlink = lower_dir_dentry->d_inode->i_nlink; unlock_dir(lower_dir_dentry); if (!rc) d_drop(dentry); - dput(dentry); +out: + if (tdentry) + dput(tdentry); + if (tlower_dentry) + dput(tlower_dentry); return rc; } @@ -799,11 +832,12 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) } lower_dentry = ecryptfs_dentry_to_lower(dentry); /* This dget & mntget is released through fput at out_fput: */ + dget(lower_dentry); lower_mnt = ecryptfs_dentry_to_lower_mnt(dentry); - if ((rc = ecryptfs_open_lower_file(&lower_file, lower_dentry, lower_mnt, - O_RDWR))) { - ecryptfs_printk(KERN_ERR, - "Error opening dentry; rc = [%i]\n", rc); + mntget(lower_mnt); + lower_file = dentry_open(lower_dentry, lower_mnt, O_RDWR); + if (unlikely(IS_ERR(lower_file))) { + rc = PTR_ERR(lower_file); goto out_free; } ecryptfs_set_file_lower(&fake_ecryptfs_file, lower_file); @@ -845,8 +879,7 @@ int ecryptfs_truncate(struct dentry *dentry, loff_t new_length) = CURRENT_TIME; mark_inode_dirty_sync(inode); out_fput: - if ((rc = ecryptfs_close_lower_file(lower_file))) - printk(KERN_ERR "Error closing lower_file\n"); + fput(lower_file); out_free: if (ecryptfs_file_to_private(&fake_ecryptfs_file)) kmem_cache_free(ecryptfs_file_info_cache, diff --git a/trunk/fs/ecryptfs/keystore.c b/trunk/fs/ecryptfs/keystore.c index c3746f56d162..ba454785a0c5 100644 --- a/trunk/fs/ecryptfs/keystore.c +++ b/trunk/fs/ecryptfs/keystore.c @@ -458,16 +458,14 @@ parse_tag_11_packet(unsigned char *data, unsigned char *contents, static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_crypt_stat *crypt_stat) { + int rc = 0; struct ecryptfs_password *password_s_ptr; + struct crypto_tfm *tfm = NULL; struct scatterlist src_sg[2], dst_sg[2]; struct mutex *tfm_mutex = NULL; /* TODO: Use virt_to_scatterlist for these */ char *encrypted_session_key; char *session_key; - struct blkcipher_desc desc = { - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; - int rc = 0; password_s_ptr = &auth_tok->token.password; if (ECRYPTFS_CHECK_FLAG(password_s_ptr->flags, @@ -484,37 +482,30 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, if (!strcmp(crypt_stat->cipher, crypt_stat->mount_crypt_stat->global_default_cipher_name) && crypt_stat->mount_crypt_stat->global_key_tfm) { - desc.tfm = crypt_stat->mount_crypt_stat->global_key_tfm; + tfm = crypt_stat->mount_crypt_stat->global_key_tfm; tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex; } else { - char *full_alg_name; - - rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, - crypt_stat->cipher, - "ecb"); - if (rc) - goto out; - desc.tfm = crypto_alloc_blkcipher(full_alg_name, 0, - CRYPTO_ALG_ASYNC); - kfree(full_alg_name); - if (IS_ERR(desc.tfm)) { - rc = PTR_ERR(desc.tfm); - printk(KERN_ERR "Error allocating crypto context; " - "rc = [%d]\n", rc); + tfm = crypto_alloc_tfm(crypt_stat->cipher, + CRYPTO_TFM_REQ_WEAK_KEY); + if (!tfm) { + printk(KERN_ERR "Error allocating crypto context\n"); + rc = -ENOMEM; goto out; } - crypto_blkcipher_set_flags(desc.tfm, CRYPTO_TFM_REQ_WEAK_KEY); } - if (tfm_mutex) - mutex_lock(tfm_mutex); - rc = crypto_blkcipher_setkey(desc.tfm, - password_s_ptr->session_key_encryption_key, - crypt_stat->key_size); - if (rc < 0) { - printk(KERN_ERR "Error setting key for crypto context\n"); + if (password_s_ptr->session_key_encryption_key_bytes + < crypto_tfm_alg_min_keysize(tfm)) { + printk(KERN_WARNING "Session key encryption key is [%d] bytes; " + "minimum keysize for selected cipher is [%d] bytes.\n", + password_s_ptr->session_key_encryption_key_bytes, + crypto_tfm_alg_min_keysize(tfm)); rc = -EINVAL; - goto out_free_tfm; + goto out; } + if (tfm_mutex) + mutex_lock(tfm_mutex); + crypto_cipher_setkey(tfm, password_s_ptr->session_key_encryption_key, + crypt_stat->key_size); /* TODO: virt_to_scatterlist */ encrypted_session_key = (char *)__get_free_page(GFP_KERNEL); if (!encrypted_session_key) { @@ -540,12 +531,9 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, auth_tok->session_key.decrypted_key_size = auth_tok->session_key.encrypted_key_size; dst_sg[0].length = auth_tok->session_key.encrypted_key_size; - rc = crypto_blkcipher_decrypt(&desc, dst_sg, src_sg, - auth_tok->session_key.encrypted_key_size); - if (rc) { - printk(KERN_ERR "Error decrypting; rc = [%d]\n", rc); - goto out_free_memory; - } + /* TODO: Handle error condition */ + crypto_cipher_decrypt(tfm, dst_sg, src_sg, + auth_tok->session_key.encrypted_key_size); auth_tok->session_key.decrypted_key_size = auth_tok->session_key.encrypted_key_size; memcpy(auth_tok->session_key.decrypted_key, session_key, @@ -558,7 +546,6 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, if (ecryptfs_verbosity > 0) ecryptfs_dump_hex(crypt_stat->key, crypt_stat->key_size); -out_free_memory: memset(encrypted_session_key, 0, PAGE_CACHE_SIZE); free_page((unsigned long)encrypted_session_key); memset(session_key, 0, PAGE_CACHE_SIZE); @@ -567,7 +554,7 @@ static int decrypt_session_key(struct ecryptfs_auth_tok *auth_tok, if (tfm_mutex) mutex_unlock(tfm_mutex); else - crypto_free_blkcipher(desc.tfm); + crypto_free_tfm(tfm); out: return rc; } @@ -816,21 +803,19 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, struct ecryptfs_crypt_stat *crypt_stat, struct ecryptfs_key_record *key_rec, size_t *packet_size) { + int rc = 0; + size_t i; size_t signature_is_valid = 0; size_t encrypted_session_key_valid = 0; char session_key_encryption_key[ECRYPTFS_MAX_KEY_BYTES]; struct scatterlist dest_sg[2]; struct scatterlist src_sg[2]; + struct crypto_tfm *tfm = NULL; struct mutex *tfm_mutex = NULL; size_t key_rec_size; size_t packet_size_length; size_t cipher_code; - struct blkcipher_desc desc = { - .tfm = NULL, - .flags = CRYPTO_TFM_REQ_MAY_SLEEP - }; - int rc = 0; (*packet_size) = 0; /* Check for a valid signature on the auth_tok */ @@ -897,48 +882,33 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, if (!strcmp(crypt_stat->cipher, crypt_stat->mount_crypt_stat->global_default_cipher_name) && crypt_stat->mount_crypt_stat->global_key_tfm) { - desc.tfm = crypt_stat->mount_crypt_stat->global_key_tfm; + tfm = crypt_stat->mount_crypt_stat->global_key_tfm; tfm_mutex = &crypt_stat->mount_crypt_stat->global_key_tfm_mutex; - } else { - char *full_alg_name; - - rc = ecryptfs_crypto_api_algify_cipher_name(&full_alg_name, - crypt_stat->cipher, - "ecb"); - if (rc) - goto out; - desc.tfm = crypto_alloc_blkcipher(full_alg_name, 0, - CRYPTO_ALG_ASYNC); - kfree(full_alg_name); - if (IS_ERR(desc.tfm)) { - rc = PTR_ERR(desc.tfm); - ecryptfs_printk(KERN_ERR, "Could not initialize crypto " - "context for cipher [%s]; rc = [%d]\n", - crypt_stat->cipher, rc); - goto out; - } - crypto_blkcipher_set_flags(desc.tfm, CRYPTO_TFM_REQ_WEAK_KEY); + } else + tfm = crypto_alloc_tfm(crypt_stat->cipher, 0); + if (!tfm) { + ecryptfs_printk(KERN_ERR, "Could not initialize crypto " + "context for cipher [%s]\n", + crypt_stat->cipher); + rc = -EINVAL; + goto out; } if (tfm_mutex) mutex_lock(tfm_mutex); - rc = crypto_blkcipher_setkey(desc.tfm, session_key_encryption_key, - crypt_stat->key_size); + rc = crypto_cipher_setkey(tfm, session_key_encryption_key, + crypt_stat->key_size); if (rc < 0) { if (tfm_mutex) mutex_unlock(tfm_mutex); ecryptfs_printk(KERN_ERR, "Error setting key for crypto " - "context; rc = [%d]\n", rc); + "context\n"); goto out; } rc = 0; ecryptfs_printk(KERN_DEBUG, "Encrypting [%d] bytes of the key\n", crypt_stat->key_size); - rc = crypto_blkcipher_encrypt(&desc, dest_sg, src_sg, - (*key_rec).enc_key_size); - if (rc) { - printk(KERN_ERR "Error encrypting; rc = [%d]\n", rc); - goto out; - } + crypto_cipher_encrypt(tfm, dest_sg, src_sg, + (*key_rec).enc_key_size); if (tfm_mutex) mutex_unlock(tfm_mutex); ecryptfs_printk(KERN_DEBUG, "This should be the encrypted key:\n"); @@ -1001,8 +971,8 @@ write_tag_3_packet(char *dest, size_t max, struct ecryptfs_auth_tok *auth_tok, (*key_rec).enc_key_size); (*packet_size) += (*key_rec).enc_key_size; out: - if (desc.tfm && !tfm_mutex) - crypto_free_blkcipher(desc.tfm); + if (tfm && !tfm_mutex) + crypto_free_tfm(tfm); if (rc) (*packet_size) = 0; return rc; diff --git a/trunk/fs/ecryptfs/main.c b/trunk/fs/ecryptfs/main.c index a78d87d14baf..5938a232d11b 100644 --- a/trunk/fs/ecryptfs/main.c +++ b/trunk/fs/ecryptfs/main.c @@ -208,6 +208,7 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) char *cipher_name_dst; char *cipher_name_src; char *cipher_key_bytes_src; + struct crypto_tfm *tmp_tfm; int cipher_name_len; if (!options) { @@ -304,19 +305,25 @@ static int ecryptfs_parse_options(struct super_block *sb, char *options) = '\0'; } if (!cipher_key_bytes_set) { - mount_crypt_stat->global_default_cipher_key_size = 0; + mount_crypt_stat->global_default_cipher_key_size = + ECRYPTFS_DEFAULT_KEY_BYTES; + ecryptfs_printk(KERN_DEBUG, "Cipher key size was not " + "specified. Defaulting to [%d]\n", + mount_crypt_stat-> + global_default_cipher_key_size); } rc = ecryptfs_process_cipher( + &tmp_tfm, &mount_crypt_stat->global_key_tfm, mount_crypt_stat->global_default_cipher_name, - &mount_crypt_stat->global_default_cipher_key_size); + mount_crypt_stat->global_default_cipher_key_size); + if (tmp_tfm) + crypto_free_tfm(tmp_tfm); if (rc) { printk(KERN_ERR "Error attempting to initialize cipher [%s] " "with key size [%Zd] bytes; rc = [%d]\n", mount_crypt_stat->global_default_cipher_name, mount_crypt_stat->global_default_cipher_key_size, rc); - mount_crypt_stat->global_key_tfm = NULL; - mount_crypt_stat->global_auth_tok_key = NULL; rc = -EINVAL; goto out; } diff --git a/trunk/fs/ecryptfs/super.c b/trunk/fs/ecryptfs/super.c index 825757ae4867..c337c0410fb1 100644 --- a/trunk/fs/ecryptfs/super.c +++ b/trunk/fs/ecryptfs/super.c @@ -137,6 +137,23 @@ static void ecryptfs_clear_inode(struct inode *inode) iput(ecryptfs_inode_to_lower(inode)); } +/** + * ecryptfs_umount_begin + * + * Called in do_umount(). + */ +static void ecryptfs_umount_begin(struct vfsmount *vfsmnt, int flags) +{ + struct vfsmount *lower_mnt = + ecryptfs_dentry_to_lower_mnt(vfsmnt->mnt_sb->s_root); + struct super_block *lower_sb; + + mntput(lower_mnt); + lower_sb = lower_mnt->mnt_sb; + if (lower_sb->s_op->umount_begin) + lower_sb->s_op->umount_begin(lower_mnt, flags); +} + /** * ecryptfs_show_options * @@ -176,5 +193,6 @@ struct super_operations ecryptfs_sops = { .statfs = ecryptfs_statfs, .remount_fs = NULL, .clear_inode = ecryptfs_clear_inode, + .umount_begin = ecryptfs_umount_begin, .show_options = ecryptfs_show_options }; diff --git a/trunk/include/asm-sh/unistd.h b/trunk/include/asm-sh/unistd.h index f1a0cbc966be..1c2abde122cd 100644 --- a/trunk/include/asm-sh/unistd.h +++ b/trunk/include/asm-sh/unistd.h @@ -324,8 +324,11 @@ #define __NR_sync_file_range 314 #define __NR_tee 315 #define __NR_vmsplice 316 +#define __NR_move_pages 317 +#define __NR_getcpu 318 +#define __NR_epoll_pwait 319 -#define NR_syscalls 317 +#define NR_syscalls 320 #ifdef __KERNEL__ diff --git a/trunk/include/asm-um/common.lds.S b/trunk/include/asm-um/common.lds.S index f0454516dd31..1010153faaf9 100644 --- a/trunk/include/asm-um/common.lds.S +++ b/trunk/include/asm-um/common.lds.S @@ -42,7 +42,13 @@ __initcall_start = .; .initcall.init : { - INITCALLS + *(.initcall1.init) + *(.initcall2.init) + *(.initcall3.init) + *(.initcall4.init) + *(.initcall5.init) + *(.initcall6.init) + *(.initcall7.init) } __initcall_end = .; diff --git a/trunk/kernel/taskstats.c b/trunk/kernel/taskstats.c index f45c5e70773c..2039585ec5e1 100644 --- a/trunk/kernel/taskstats.c +++ b/trunk/kernel/taskstats.c @@ -455,9 +455,10 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, int is_thread_group; struct nlattr *na; - if (!family_registered) + if (!family_registered || !tidstats) return; + rc = 0; /* * Size includes space for nested attributes */ @@ -465,15 +466,8 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, nla_total_size(sizeof(struct taskstats)) + nla_total_size(0); is_thread_group = (tsk->signal->stats != NULL); - if (is_thread_group) { - /* PID + STATS + TGID + STATS */ - size = 2 * size; - /* fill the tsk->signal->stats structure */ - fill_tgid_exit(tsk); - } - - if (!tidstats) - return; + if (is_thread_group) + size = 2 * size; /* PID + STATS + TGID + STATS */ rc = prepare_reply(NULL, TASKSTATS_CMD_NEW, &rep_skb, &reply, size); if (rc < 0) @@ -493,8 +487,11 @@ void taskstats_exit_send(struct task_struct *tsk, struct taskstats *tidstats, goto send; /* + * tsk has/had a thread group so fill the tsk->signal->stats structure * Doesn't matter if tsk is the leader or the last group member leaving */ + + fill_tgid_exit(tsk); if (!group_dead) goto send; diff --git a/trunk/net/appletalk/ddp.c b/trunk/net/appletalk/ddp.c index 485e35c3b28b..708e2e0371af 100644 --- a/trunk/net/appletalk/ddp.c +++ b/trunk/net/appletalk/ddp.c @@ -1584,6 +1584,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr if (usat->sat_addr.s_net || usat->sat_addr.s_node == ATADDR_ANYNODE) { rt = atrtr_find(&usat->sat_addr); + dev = rt->dev; } else { struct atalk_addr at_hint; @@ -1591,6 +1592,7 @@ static int atalk_sendmsg(struct kiocb *iocb, struct socket *sock, struct msghdr at_hint.s_net = at->src_net; rt = atrtr_find(&at_hint); + dev = rt->dev; } if (!rt) return -ENETUNREACH; diff --git a/trunk/net/core/skbuff.c b/trunk/net/core/skbuff.c index f735455dc5d1..3c23760c5827 100644 --- a/trunk/net/core/skbuff.c +++ b/trunk/net/core/skbuff.c @@ -1946,7 +1946,7 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) do { struct sk_buff *nskb; skb_frag_t *frag; - int hsize; + int hsize, nsize; int k; int size; @@ -1957,10 +1957,11 @@ struct sk_buff *skb_segment(struct sk_buff *skb, int features) hsize = skb_headlen(skb) - offset; if (hsize < 0) hsize = 0; - if (hsize > len || !sg) - hsize = len; + nsize = hsize + doffset; + if (nsize > len + doffset || !sg) + nsize = len + doffset; - nskb = alloc_skb(hsize + doffset + headroom, GFP_ATOMIC); + nskb = alloc_skb(nsize + headroom, GFP_ATOMIC); if (unlikely(!nskb)) goto err; diff --git a/trunk/net/dccp/ccids/ccid2.c b/trunk/net/dccp/ccids/ccid2.c index 162032baeac0..2fbb84bf4e26 100644 --- a/trunk/net/dccp/ccids/ccid2.c +++ b/trunk/net/dccp/ccids/ccid2.c @@ -352,14 +352,14 @@ static void ccid2_hc_tx_packet_sent(struct sock *sk, int more, int len) #ifdef CONFIG_IP_DCCP_CCID2_DEBUG ccid2_pr_debug("pipe=%d\n", hctx->ccid2hctx_pipe); - ccid2_pr_debug("Sent: seq=%llu\n", (unsigned long long)seq); + ccid2_pr_debug("Sent: seq=%llu\n", seq); do { struct ccid2_seq *seqp = hctx->ccid2hctx_seqt; while (seqp != hctx->ccid2hctx_seqh) { ccid2_pr_debug("out seq=%llu acked=%d time=%lu\n", - (unsigned long long)seqp->ccid2s_seq, - seqp->ccid2s_acked, seqp->ccid2s_sent); + seqp->ccid2s_seq, seqp->ccid2s_acked, + seqp->ccid2s_sent); seqp = seqp->ccid2s_next; } } while (0); @@ -480,8 +480,7 @@ static inline void ccid2_new_ack(struct sock *sk, /* first measurement */ if (hctx->ccid2hctx_srtt == -1) { ccid2_pr_debug("R: %lu Time=%lu seq=%llu\n", - r, jiffies, - (unsigned long long)seqp->ccid2s_seq); + r, jiffies, seqp->ccid2s_seq); ccid2_change_srtt(hctx, r); hctx->ccid2hctx_rttvar = r >> 1; } else { @@ -637,9 +636,8 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) u64 ackno_end_rl; dccp_set_seqno(&ackno_end_rl, ackno - rl); - ccid2_pr_debug("ackvec start:%llu end:%llu\n", - (unsigned long long)ackno, - (unsigned long long)ackno_end_rl); + ccid2_pr_debug("ackvec start:%llu end:%llu\n", ackno, + ackno_end_rl); /* if the seqno we are analyzing is larger than the * current ackno, then move towards the tail of our * seqnos. @@ -674,7 +672,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) seqp->ccid2s_acked = 1; ccid2_pr_debug("Got ack for %llu\n", - (unsigned long long)seqp->ccid2s_seq); + seqp->ccid2s_seq); ccid2_hc_tx_dec_pipe(sk); } if (seqp == hctx->ccid2hctx_seqt) { @@ -720,7 +718,7 @@ static void ccid2_hc_tx_packet_recv(struct sock *sk, struct sk_buff *skb) while (1) { if (!seqp->ccid2s_acked) { ccid2_pr_debug("Packet lost: %llu\n", - (unsigned long long)seqp->ccid2s_seq); + seqp->ccid2s_seq); /* XXX need to traverse from tail -> head in * order to detect multiple congestion events in * one ack vector. diff --git a/trunk/net/ipv4/cipso_ipv4.c b/trunk/net/ipv4/cipso_ipv4.c index 6460233407c7..e2077a3aa8c0 100644 --- a/trunk/net/ipv4/cipso_ipv4.c +++ b/trunk/net/ipv4/cipso_ipv4.c @@ -1307,8 +1307,7 @@ int cipso_v4_socket_setattr(const struct socket *sock, /* We can't use ip_options_get() directly because it makes a call to * ip_options_get_alloc() which allocates memory with GFP_KERNEL and - * we won't always have CAP_NET_RAW even though we _always_ want to - * set the IPOPT_CIPSO option. */ + * we can't block here. */ opt_len = (buf_len + 3) & ~3; opt = kzalloc(sizeof(*opt) + opt_len, GFP_ATOMIC); if (opt == NULL) { @@ -1318,9 +1317,11 @@ int cipso_v4_socket_setattr(const struct socket *sock, memcpy(opt->__data, buf, buf_len); opt->optlen = opt_len; opt->is_data = 1; - opt->cipso = sizeof(struct iphdr); kfree(buf); buf = NULL; + ret_val = ip_options_compile(opt, NULL); + if (ret_val != 0) + goto socket_setattr_failure; sk_inet = inet_sk(sk); if (sk_inet->is_icsk) { diff --git a/trunk/net/ipv4/ip_options.c b/trunk/net/ipv4/ip_options.c index 9f02917d6f45..8dabbfc31267 100644 --- a/trunk/net/ipv4/ip_options.c +++ b/trunk/net/ipv4/ip_options.c @@ -443,7 +443,7 @@ int ip_options_compile(struct ip_options * opt, struct sk_buff * skb) opt->router_alert = optptr - iph; break; case IPOPT_CIPSO: - if ((!skb && !capable(CAP_NET_RAW)) || opt->cipso) { + if (opt->cipso) { pp_ptr = optptr; goto error; } diff --git a/trunk/net/ipv4/netfilter/arp_tables.c b/trunk/net/ipv4/netfilter/arp_tables.c index 413c2d0a1f3d..0849f1cced13 100644 --- a/trunk/net/ipv4/netfilter/arp_tables.c +++ b/trunk/net/ipv4/netfilter/arp_tables.c @@ -466,13 +466,7 @@ static inline int check_entry(struct arpt_entry *e, const char *name, unsigned i return -EINVAL; } - if (e->target_offset + sizeof(struct arpt_entry_target) > e->next_offset) - return -EINVAL; - t = arpt_get_target(e); - if (e->target_offset + t->u.target_size > e->next_offset) - return -EINVAL; - target = try_then_request_module(xt_find_target(NF_ARP, t->u.user.name, t->u.user.revision), "arpt_%s", t->u.user.name); @@ -627,18 +621,20 @@ static int translate_table(const char *name, } } + if (!mark_source_chains(newinfo, valid_hooks, entry0)) { + duprintf("Looping hook\n"); + return -ELOOP; + } + /* Finally, each sanity check must pass */ i = 0; ret = ARPT_ENTRY_ITERATE(entry0, newinfo->size, check_entry, name, size, &i); - if (ret != 0) - goto cleanup; - - ret = -ELOOP; - if (!mark_source_chains(newinfo, valid_hooks, entry0)) { - duprintf("Looping hook\n"); - goto cleanup; + if (ret != 0) { + ARPT_ENTRY_ITERATE(entry0, newinfo->size, + cleanup_entry, &i); + return ret; } /* And one copy for every other CPU */ @@ -647,9 +643,6 @@ static int translate_table(const char *name, memcpy(newinfo->entries[i], entry0, newinfo->size); } - return 0; -cleanup: - ARPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i); return ret; } diff --git a/trunk/net/ipv4/netfilter/ip_tables.c b/trunk/net/ipv4/netfilter/ip_tables.c index 8a455439b128..4b90927619b8 100644 --- a/trunk/net/ipv4/netfilter/ip_tables.c +++ b/trunk/net/ipv4/netfilter/ip_tables.c @@ -547,18 +547,12 @@ check_entry(struct ipt_entry *e, const char *name, unsigned int size, return -EINVAL; } - if (e->target_offset + sizeof(struct ipt_entry_target) > e->next_offset) - return -EINVAL; - j = 0; ret = IPT_MATCH_ITERATE(e, check_match, name, &e->ip, e->comefrom, &j); if (ret != 0) goto cleanup_matches; t = ipt_get_target(e); - ret = -EINVAL; - if (e->target_offset + t->u.target_size > e->next_offset) - goto cleanup_matches; target = try_then_request_module(xt_find_target(AF_INET, t->u.user.name, t->u.user.revision), @@ -718,17 +712,19 @@ translate_table(const char *name, } } + if (!mark_source_chains(newinfo, valid_hooks, entry0)) + return -ELOOP; + /* Finally, each sanity check must pass */ i = 0; ret = IPT_ENTRY_ITERATE(entry0, newinfo->size, check_entry, name, size, &i); - if (ret != 0) - goto cleanup; - - ret = -ELOOP; - if (!mark_source_chains(newinfo, valid_hooks, entry0)) - goto cleanup; + if (ret != 0) { + IPT_ENTRY_ITERATE(entry0, newinfo->size, + cleanup_entry, &i); + return ret; + } /* And one copy for every other CPU */ for_each_possible_cpu(i) { @@ -736,9 +732,6 @@ translate_table(const char *name, memcpy(newinfo->entries[i], entry0, newinfo->size); } - return 0; -cleanup: - IPT_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i); return ret; } @@ -1470,10 +1463,6 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, return -EINVAL; } - if (e->target_offset + sizeof(struct compat_xt_entry_target) > - e->next_offset) - return -EINVAL; - off = 0; entry_offset = (void *)e - (void *)base; j = 0; @@ -1483,9 +1472,6 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, goto cleanup_matches; t = ipt_get_target(e); - ret = -EINVAL; - if (e->target_offset + t->u.target_size > e->next_offset) - goto cleanup_matches; target = try_then_request_module(xt_find_target(AF_INET, t->u.user.name, t->u.user.revision), @@ -1527,7 +1513,7 @@ check_compat_entry_size_and_hooks(struct ipt_entry *e, static inline int compat_copy_match_from_user(struct ipt_entry_match *m, void **dstptr, compat_uint_t *size, const char *name, - const struct ipt_ip *ip, unsigned int hookmask) + const struct ipt_ip *ip, unsigned int hookmask, int *i) { struct ipt_entry_match *dm; struct ipt_match *match; @@ -1540,13 +1526,22 @@ static inline int compat_copy_match_from_user(struct ipt_entry_match *m, ret = xt_check_match(match, AF_INET, dm->u.match_size - sizeof(*dm), name, hookmask, ip->proto, ip->invflags & IPT_INV_PROTO); - if (!ret && m->u.kernel.match->checkentry + if (ret) + goto err; + + if (m->u.kernel.match->checkentry && !m->u.kernel.match->checkentry(name, ip, match, dm->data, hookmask)) { duprintf("ip_tables: check failed for `%s'.\n", m->u.kernel.match->name); ret = -EINVAL; + goto err; } + (*i)++; + return 0; + +err: + module_put(m->u.kernel.match->me); return ret; } @@ -1558,18 +1553,19 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, struct ipt_target *target; struct ipt_entry *de; unsigned int origsize; - int ret, h; + int ret, h, j; ret = 0; origsize = *size; de = (struct ipt_entry *)*dstptr; memcpy(de, e, sizeof(struct ipt_entry)); + j = 0; *dstptr += sizeof(struct compat_ipt_entry); ret = IPT_MATCH_ITERATE(e, compat_copy_match_from_user, dstptr, size, - name, &de->ip, de->comefrom); + name, &de->ip, de->comefrom, &j); if (ret) - goto err; + goto cleanup_matches; de->target_offset = e->target_offset - (origsize - *size); t = ipt_get_target(e); target = t->u.kernel.target; @@ -1603,7 +1599,12 @@ static int compat_copy_entry_from_user(struct ipt_entry *e, void **dstptr, goto err; } ret = 0; + return ret; + err: + module_put(t->u.kernel.target->me); +cleanup_matches: + IPT_MATCH_ITERATE(e, cleanup_match, &j); return ret; } @@ -1617,7 +1618,7 @@ translate_compat_table(const char *name, unsigned int *hook_entries, unsigned int *underflows) { - unsigned int i, j; + unsigned int i; struct xt_table_info *newinfo, *info; void *pos, *entry0, *entry1; unsigned int size; @@ -1635,21 +1636,21 @@ translate_compat_table(const char *name, } duprintf("translate_compat_table: size %u\n", info->size); - j = 0; + i = 0; xt_compat_lock(AF_INET); /* Walk through entries, checking offsets. */ ret = IPT_ENTRY_ITERATE(entry0, total_size, check_compat_entry_size_and_hooks, info, &size, entry0, entry0 + total_size, - hook_entries, underflows, &j, name); + hook_entries, underflows, &i, name); if (ret != 0) goto out_unlock; ret = -EINVAL; - if (j != number) { + if (i != number) { duprintf("translate_compat_table: %u not %u entries\n", - j, number); + i, number); goto out_unlock; } @@ -1708,10 +1709,8 @@ translate_compat_table(const char *name, free_newinfo: xt_free_table_info(newinfo); out: - IPT_ENTRY_ITERATE(entry0, total_size, cleanup_entry, &j); return ret; out_unlock: - compat_flush_offsets(); xt_compat_unlock(AF_INET); goto out; } diff --git a/trunk/net/ipv4/raw.c b/trunk/net/ipv4/raw.c index 5c31dead2bdc..b430cf2a4f66 100644 --- a/trunk/net/ipv4/raw.c +++ b/trunk/net/ipv4/raw.c @@ -329,7 +329,7 @@ static int raw_send_hdrinc(struct sock *sk, void *from, size_t length, return err; } -static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) +static void raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) { struct iovec *iov; u8 __user *type = NULL; @@ -338,7 +338,7 @@ static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) unsigned int i; if (!msg->msg_iov) - return 0; + return; for (i = 0; i < msg->msg_iovlen; i++) { iov = &msg->msg_iov[i]; @@ -360,9 +360,8 @@ static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) code = iov->iov_base; if (type && code) { - if (get_user(fl->fl_icmp_type, type) || - get_user(fl->fl_icmp_code, code)) - return -EFAULT; + get_user(fl->fl_icmp_type, type); + get_user(fl->fl_icmp_code, code); probed = 1; } break; @@ -373,7 +372,6 @@ static int raw_probe_proto_opt(struct flowi *fl, struct msghdr *msg) if (probed) break; } - return 0; } static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, @@ -482,11 +480,8 @@ static int raw_sendmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg, .proto = inet->hdrincl ? IPPROTO_RAW : sk->sk_protocol, }; - if (!inet->hdrincl) { - err = raw_probe_proto_opt(&fl, msg); - if (err) - goto done; - } + if (!inet->hdrincl) + raw_probe_proto_opt(&fl, msg); security_sk_classify_flow(sk, &fl); err = ip_route_output_flow(&rt, &fl, sk, !(msg->msg_flags&MSG_DONTWAIT)); diff --git a/trunk/net/ipv6/ip6_flowlabel.c b/trunk/net/ipv6/ip6_flowlabel.c index 6d4533b58dca..1d672b0547f2 100644 --- a/trunk/net/ipv6/ip6_flowlabel.c +++ b/trunk/net/ipv6/ip6_flowlabel.c @@ -330,10 +330,8 @@ fl_create(struct in6_flowlabel_req *freq, char __user *optval, int optlen, int * fl->share = freq->flr_share; addr_type = ipv6_addr_type(&freq->flr_dst); if ((addr_type&IPV6_ADDR_MAPPED) - || addr_type == IPV6_ADDR_ANY) { - err = -EINVAL; + || addr_type == IPV6_ADDR_ANY) goto done; - } ipv6_addr_copy(&fl->dst, &freq->flr_dst); atomic_set(&fl->users, 1); switch (fl->share) { @@ -589,8 +587,6 @@ static struct ip6_flowlabel *ip6fl_get_next(struct seq_file *seq, struct ip6_flo while (!fl) { if (++state->bucket <= FL_HASH_MASK) fl = fl_ht[state->bucket]; - else - break; } return fl; } @@ -627,13 +623,9 @@ static void ip6fl_seq_stop(struct seq_file *seq, void *v) read_unlock_bh(&ip6_fl_lock); } -static int ip6fl_seq_show(struct seq_file *seq, void *v) +static void ip6fl_fl_seq_show(struct seq_file *seq, struct ip6_flowlabel *fl) { - if (v == SEQ_START_TOKEN) - seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", - "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); - else { - struct ip6_flowlabel *fl = v; + while(fl) { seq_printf(seq, "%05X %-1d %-6d %-6d %-6ld %-8ld " NIP6_SEQFMT " %-4d\n", (unsigned)ntohl(fl->label), @@ -644,7 +636,17 @@ static int ip6fl_seq_show(struct seq_file *seq, void *v) (long)(fl->expires - jiffies)/HZ, NIP6(fl->dst), fl->opt ? fl->opt->opt_nflen : 0); + fl = fl->next; } +} + +static int ip6fl_seq_show(struct seq_file *seq, void *v) +{ + if (v == SEQ_START_TOKEN) + seq_printf(seq, "%-5s %-1s %-6s %-6s %-6s %-8s %-32s %s\n", + "Label", "S", "Owner", "Users", "Linger", "Expires", "Dst", "Opt"); + else + ip6fl_fl_seq_show(seq, v); return 0; } diff --git a/trunk/net/ipv6/netfilter/Kconfig b/trunk/net/ipv6/netfilter/Kconfig index d7c45a9c15fe..4bc4e5b33794 100644 --- a/trunk/net/ipv6/netfilter/Kconfig +++ b/trunk/net/ipv6/netfilter/Kconfig @@ -40,7 +40,7 @@ config IP6_NF_QUEUE To compile it as a module, choose M here. If unsure, say N. config IP6_NF_IPTABLES - tristate "IP6 tables support (required for filtering)" + tristate "IP6 tables support (required for filtering/masq/NAT)" depends on NETFILTER_XTABLES help ip6tables is a general, extensible packet identification framework. diff --git a/trunk/net/ipv6/netfilter/ip6_tables.c b/trunk/net/ipv6/netfilter/ip6_tables.c index 167c2ea88f6b..53bf977cca63 100644 --- a/trunk/net/ipv6/netfilter/ip6_tables.c +++ b/trunk/net/ipv6/netfilter/ip6_tables.c @@ -586,19 +586,12 @@ check_entry(struct ip6t_entry *e, const char *name, unsigned int size, return -EINVAL; } - if (e->target_offset + sizeof(struct ip6t_entry_target) > - e->next_offset) - return -EINVAL; - j = 0; ret = IP6T_MATCH_ITERATE(e, check_match, name, &e->ipv6, e->comefrom, &j); if (ret != 0) goto cleanup_matches; t = ip6t_get_target(e); - ret = -EINVAL; - if (e->target_offset + t->u.target_size > e->next_offset) - goto cleanup_matches; target = try_then_request_module(xt_find_target(AF_INET6, t->u.user.name, t->u.user.revision), @@ -758,17 +751,19 @@ translate_table(const char *name, } } + if (!mark_source_chains(newinfo, valid_hooks, entry0)) + return -ELOOP; + /* Finally, each sanity check must pass */ i = 0; ret = IP6T_ENTRY_ITERATE(entry0, newinfo->size, check_entry, name, size, &i); - if (ret != 0) - goto cleanup; - - ret = -ELOOP; - if (!mark_source_chains(newinfo, valid_hooks, entry0)) - goto cleanup; + if (ret != 0) { + IP6T_ENTRY_ITERATE(entry0, newinfo->size, + cleanup_entry, &i); + return ret; + } /* And one copy for every other CPU */ for_each_possible_cpu(i) { @@ -776,9 +771,6 @@ translate_table(const char *name, memcpy(newinfo->entries[i], entry0, newinfo->size); } - return 0; -cleanup: - IP6T_ENTRY_ITERATE(entry0, newinfo->size, cleanup_entry, &i); return ret; } diff --git a/trunk/net/ipv6/raw.c b/trunk/net/ipv6/raw.c index d6dedc4aec77..d09329ca3267 100644 --- a/trunk/net/ipv6/raw.c +++ b/trunk/net/ipv6/raw.c @@ -604,7 +604,7 @@ static int rawv6_send_hdrinc(struct sock *sk, void *from, int length, return err; } -static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) +static void rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) { struct iovec *iov; u8 __user *type = NULL; @@ -616,7 +616,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) int i; if (!msg->msg_iov) - return 0; + return; for (i = 0; i < msg->msg_iovlen; i++) { iov = &msg->msg_iov[i]; @@ -638,9 +638,8 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) code = iov->iov_base; if (type && code) { - if (get_user(fl->fl_icmp_type, type) || - get_user(fl->fl_icmp_code, code)) - return -EFAULT; + get_user(fl->fl_icmp_type, type); + get_user(fl->fl_icmp_code, code); probed = 1; } break; @@ -651,8 +650,7 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) /* check if type field is readable or not. */ if (iov->iov_len > 2 - len) { u8 __user *p = iov->iov_base; - if (get_user(fl->fl_mh_type, &p[2 - len])) - return -EFAULT; + get_user(fl->fl_mh_type, &p[2 - len]); probed = 1; } else len += iov->iov_len; @@ -666,7 +664,6 @@ static int rawv6_probe_proto_opt(struct flowi *fl, struct msghdr *msg) if (probed) break; } - return 0; } static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, @@ -790,9 +787,7 @@ static int rawv6_sendmsg(struct kiocb *iocb, struct sock *sk, opt = ipv6_fixup_options(&opt_space, opt); fl.proto = proto; - err = rawv6_probe_proto_opt(&fl, msg); - if (err) - goto out; + rawv6_probe_proto_opt(&fl, msg); ipv6_addr_copy(&fl.fl6_dst, daddr); if (ipv6_addr_any(&fl.fl6_src) && !ipv6_addr_any(&np->saddr)) diff --git a/trunk/net/netfilter/nf_conntrack_core.c b/trunk/net/netfilter/nf_conntrack_core.c index 836541e509fe..093b3ddc513c 100644 --- a/trunk/net/netfilter/nf_conntrack_core.c +++ b/trunk/net/netfilter/nf_conntrack_core.c @@ -1520,10 +1520,9 @@ get_next_corpse(int (*iter)(struct nf_conn *i, void *data), if (iter(ct, data)) goto found; } - write_unlock_bh(&nf_conntrack_lock); return NULL; found: - atomic_inc(&ct->ct_general.use); + atomic_inc(&nf_ct_tuplehash_to_ctrack(h)->ct_general.use); write_unlock_bh(&nf_conntrack_lock); return ct; } diff --git a/trunk/net/netlink/af_netlink.c b/trunk/net/netlink/af_netlink.c index d527c8977b1f..d56e0d21f919 100644 --- a/trunk/net/netlink/af_netlink.c +++ b/trunk/net/netlink/af_netlink.c @@ -1075,9 +1075,8 @@ static int netlink_getsockopt(struct socket *sock, int level, int optname, return -EINVAL; len = sizeof(int); val = nlk->flags & NETLINK_RECV_PKTINFO ? 1 : 0; - if (put_user(len, optlen) || - put_user(val, optval)) - return -EFAULT; + put_user(len, optlen); + put_user(val, optval); err = 0; break; default: diff --git a/trunk/net/sctp/associola.c b/trunk/net/sctp/associola.c index ed0445fe85e7..27329ce9c311 100644 --- a/trunk/net/sctp/associola.c +++ b/trunk/net/sctp/associola.c @@ -346,18 +346,11 @@ void sctp_association_free(struct sctp_association *asoc) struct list_head *pos, *temp; int i; - /* Only real associations count against the endpoint, so - * don't bother for if this is a temporary association. - */ - if (!asoc->temp) { - list_del(&asoc->asocs); + list_del(&asoc->asocs); - /* Decrement the backlog value for a TCP-style listening - * socket. - */ - if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) - sk->sk_ack_backlog--; - } + /* Decrement the backlog value for a TCP-style listening socket. */ + if (sctp_style(sk, TCP) && sctp_sstate(sk, LISTENING)) + sk->sk_ack_backlog--; /* Mark as dead, so other users can know this structure is * going away. diff --git a/trunk/net/sctp/endpointola.c b/trunk/net/sctp/endpointola.c index 9b6b394b66f6..35c49ff2d062 100644 --- a/trunk/net/sctp/endpointola.c +++ b/trunk/net/sctp/endpointola.c @@ -144,13 +144,6 @@ void sctp_endpoint_add_asoc(struct sctp_endpoint *ep, { struct sock *sk = ep->base.sk; - /* If this is a temporary association, don't bother - * since we'll be removing it shortly and don't - * want anyone to find it anyway. - */ - if (asoc->temp) - return; - /* Now just add it to our list of asocs */ list_add_tail(&asoc->asocs, &ep->asocs); diff --git a/trunk/net/sctp/input.c b/trunk/net/sctp/input.c index 6d82f400d13c..64f630102532 100644 --- a/trunk/net/sctp/input.c +++ b/trunk/net/sctp/input.c @@ -135,9 +135,6 @@ int sctp_rcv(struct sk_buff *skb) SCTP_INC_STATS_BH(SCTP_MIB_INSCTPPACKS); - if (skb_linearize(skb)) - goto discard_it; - sh = (struct sctphdr *) skb->h.raw; /* Pull up the IP and SCTP headers. */ @@ -771,9 +768,6 @@ static void __sctp_hash_established(struct sctp_association *asoc) /* Add an association to the hash. Local BH-safe. */ void sctp_hash_established(struct sctp_association *asoc) { - if (asoc->temp) - return; - sctp_local_bh_disable(); __sctp_hash_established(asoc); sctp_local_bh_enable(); @@ -807,9 +801,6 @@ static void __sctp_unhash_established(struct sctp_association *asoc) /* Remove association from the hash table. Local BH-safe. */ void sctp_unhash_established(struct sctp_association *asoc) { - if (asoc->temp) - return; - sctp_local_bh_disable(); __sctp_unhash_established(asoc); sctp_local_bh_enable(); diff --git a/trunk/net/sctp/protocol.c b/trunk/net/sctp/protocol.c index 5b4f82fd98f8..fac7674438a4 100644 --- a/trunk/net/sctp/protocol.c +++ b/trunk/net/sctp/protocol.c @@ -591,7 +591,7 @@ static struct sock *sctp_v4_create_accept_sk(struct sock *sk, newinet->dport = htons(asoc->peer.port); newinet->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; newinet->pmtudisc = inet->pmtudisc; - newinet->id = asoc->next_tsn ^ jiffies; + newinet->id = 0; newinet->uc_ttl = -1; newinet->mc_loop = 1; diff --git a/trunk/net/sctp/socket.c b/trunk/net/sctp/socket.c index 935bc9187fd8..9f34dec6ff8e 100644 --- a/trunk/net/sctp/socket.c +++ b/trunk/net/sctp/socket.c @@ -3372,7 +3372,6 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc, { struct sock *sk = asoc->base.sk; struct socket *sock; - struct inet_sock *inetsk; int err = 0; /* An association cannot be branched off from an already peeled-off @@ -3390,14 +3389,6 @@ SCTP_STATIC int sctp_do_peeloff(struct sctp_association *asoc, * asoc to the newsk. */ sctp_sock_migrate(sk, sock->sk, asoc, SCTP_SOCKET_UDP_HIGH_BANDWIDTH); - - /* Make peeled-off sockets more like 1-1 accepted sockets. - * Set the daddr and initialize id to something more random - */ - inetsk = inet_sk(sock->sk); - inetsk->daddr = asoc->peer.primary_addr.v4.sin_addr.s_addr; - inetsk->id = asoc->next_tsn ^ jiffies; - *sockp = sock; return err; diff --git a/trunk/net/xfrm/xfrm_user.c b/trunk/net/xfrm/xfrm_user.c index b43e7647e125..2b2e59d8ffbc 100644 --- a/trunk/net/xfrm/xfrm_user.c +++ b/trunk/net/xfrm/xfrm_user.c @@ -323,7 +323,7 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info * x->props.replay_window = p->replay_window; x->props.reqid = p->reqid; x->props.family = p->family; - memcpy(&x->props.saddr, &p->saddr, sizeof(x->props.saddr)); + x->props.saddr = p->saddr; x->props.flags = p->flags; } @@ -545,7 +545,7 @@ static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p) memcpy(&p->lft, &x->lft, sizeof(p->lft)); memcpy(&p->curlft, &x->curlft, sizeof(p->curlft)); memcpy(&p->stats, &x->stats, sizeof(p->stats)); - memcpy(&p->saddr, &x->props.saddr, sizeof(p->saddr)); + p->saddr = x->props.saddr; p->mode = x->props.mode; p->replay_window = x->props.replay_window; p->reqid = x->props.reqid; diff --git a/trunk/security/selinux/hooks.c b/trunk/security/selinux/hooks.c index 8ab5679a37a3..e9969a2fc846 100644 --- a/trunk/security/selinux/hooks.c +++ b/trunk/security/selinux/hooks.c @@ -3313,13 +3313,7 @@ static int selinux_socket_getpeername(struct socket *sock) static int selinux_socket_setsockopt(struct socket *sock,int level,int optname) { - int err; - - err = socket_has_perm(current, sock, SOCKET__SETOPT); - if (err) - return err; - - return selinux_netlbl_socket_setsockopt(sock, level, optname); + return socket_has_perm(current, sock, SOCKET__SETOPT); } static int selinux_socket_getsockopt(struct socket *sock, int level, diff --git a/trunk/security/selinux/include/selinux_netlabel.h b/trunk/security/selinux/include/selinux_netlabel.h index 9de10cc2cef2..ecab4bddaaf4 100644 --- a/trunk/security/selinux/include/selinux_netlabel.h +++ b/trunk/security/selinux/include/selinux_netlabel.h @@ -53,9 +53,6 @@ void selinux_netlbl_sk_security_init(struct sk_security_struct *ssec, void selinux_netlbl_sk_clone_security(struct sk_security_struct *ssec, struct sk_security_struct *newssec); int selinux_netlbl_inode_permission(struct inode *inode, int mask); -int selinux_netlbl_socket_setsockopt(struct socket *sock, - int level, - int optname); #else static inline void selinux_netlbl_cache_invalidate(void) { @@ -117,13 +114,6 @@ static inline int selinux_netlbl_inode_permission(struct inode *inode, { return 0; } - -static inline int selinux_netlbl_socket_setsockopt(struct socket *sock, - int level, - int optname) -{ - return 0; -} #endif /* CONFIG_NETLABEL */ #endif diff --git a/trunk/security/selinux/ss/services.c b/trunk/security/selinux/ss/services.c index bfe122764c98..b1f6fb36c699 100644 --- a/trunk/security/selinux/ss/services.c +++ b/trunk/security/selinux/ss/services.c @@ -2682,41 +2682,4 @@ u32 selinux_netlbl_socket_getpeersec_dgram(struct sk_buff *skb) return peer_sid; } - -/** - * selinux_netlbl_socket_setsockopt - Do not allow users to remove a NetLabel - * @sock: the socket - * @level: the socket level or protocol - * @optname: the socket option name - * - * Description: - * Check the setsockopt() call and if the user is trying to replace the IP - * options on a socket and a NetLabel is in place for the socket deny the - * access; otherwise allow the access. Returns zero when the access is - * allowed, -EACCES when denied, and other negative values on error. - * - */ -int selinux_netlbl_socket_setsockopt(struct socket *sock, - int level, - int optname) -{ - int rc = 0; - struct inode *inode = SOCK_INODE(sock); - struct sk_security_struct *sksec = sock->sk->sk_security; - struct inode_security_struct *isec = inode->i_security; - struct netlbl_lsm_secattr secattr; - - mutex_lock(&isec->lock); - if (level == IPPROTO_IP && optname == IP_OPTIONS && - sksec->nlbl_state == NLBL_LABELED) { - netlbl_secattr_init(&secattr); - rc = netlbl_socket_getattr(sock, &secattr); - if (rc == 0 && (secattr.cache || secattr.mls_lvl_vld)) - rc = -EACCES; - netlbl_secattr_destroy(&secattr); - } - mutex_unlock(&isec->lock); - - return rc; -} #endif /* CONFIG_NETLABEL */