diff --git a/[refs] b/[refs] index 363529f35ec7..877a46fe98f7 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 22c6b32d8d9b7adf903c19b7e108062431fdc6fc +refs/heads/master: fe6b91f47080eb17d21cbf2a39311877d57f6938 diff --git a/trunk/arch/m68k/include/asm/unistd.h b/trunk/arch/m68k/include/asm/unistd.h index 303192fc9260..43f984e93970 100644 --- a/trunk/arch/m68k/include/asm/unistd.h +++ b/trunk/arch/m68k/include/asm/unistd.h @@ -350,12 +350,10 @@ #define __NR_clock_adjtime 342 #define __NR_syncfs 343 #define __NR_setns 344 -#define __NR_process_vm_readv 345 -#define __NR_process_vm_writev 346 #ifdef __KERNEL__ -#define NR_syscalls 347 +#define NR_syscalls 345 #define __ARCH_WANT_IPC_PARSE_VERSION #define __ARCH_WANT_OLD_READDIR diff --git a/trunk/arch/m68k/kernel/syscalltable.S b/trunk/arch/m68k/kernel/syscalltable.S index ce827b376110..c468f2edaa85 100644 --- a/trunk/arch/m68k/kernel/syscalltable.S +++ b/trunk/arch/m68k/kernel/syscalltable.S @@ -365,6 +365,4 @@ ENTRY(sys_call_table) .long sys_clock_adjtime .long sys_syncfs .long sys_setns - .long sys_process_vm_readv /* 345 */ - .long sys_process_vm_writev diff --git a/trunk/drivers/base/core.c b/trunk/drivers/base/core.c index d8b3d89db043..919daa7cd5b1 100644 --- a/trunk/drivers/base/core.c +++ b/trunk/drivers/base/core.c @@ -1743,8 +1743,10 @@ void device_shutdown(void) */ list_del_init(&dev->kobj.entry); spin_unlock(&devices_kset->list_lock); - /* Disable all device's runtime power management */ - pm_runtime_disable(dev); + + /* Don't allow any more runtime suspends */ + pm_runtime_get_noresume(dev); + pm_runtime_barrier(dev); if (dev->bus && dev->bus->shutdown) { dev_dbg(dev, "shutdown\n"); diff --git a/trunk/drivers/gpu/drm/i915/i915_gem.c b/trunk/drivers/gpu/drm/i915/i915_gem.c index 60ff1b63b568..8359dc777041 100644 --- a/trunk/drivers/gpu/drm/i915/i915_gem.c +++ b/trunk/drivers/gpu/drm/i915/i915_gem.c @@ -2026,13 +2026,8 @@ i915_wait_request(struct intel_ring_buffer *ring, * to handle this, the waiter on a request often wants an associated * buffer to have made it to the inactive list, and we would need * a separate wait queue to handle that. - * - * To avoid a recursion with the ilk VT-d workaround (that calls - * gpu_idle when unbinding objects with interruptible==false) don't - * retire requests in that case (because it might call unbind if the - * active list holds the last reference to the object). */ - if (ret == 0 && dev_priv->mm.interruptible) + if (ret == 0) i915_gem_retire_requests_ring(ring); return ret; diff --git a/trunk/drivers/gpu/drm/radeon/radeon_encoders.c b/trunk/drivers/gpu/drm/radeon/radeon_encoders.c index 4b27efa4405b..06e413e6a920 100644 --- a/trunk/drivers/gpu/drm/radeon/radeon_encoders.c +++ b/trunk/drivers/gpu/drm/radeon/radeon_encoders.c @@ -233,12 +233,13 @@ u16 radeon_encoder_get_dp_bridge_encoder_id(struct drm_encoder *encoder) switch (radeon_encoder->encoder_id) { case ENCODER_OBJECT_ID_TRAVIS: case ENCODER_OBJECT_ID_NUTMEG: - return radeon_encoder->encoder_id; + return true; default: - return ENCODER_OBJECT_ID_NONE; + return false; } } - return ENCODER_OBJECT_ID_NONE; + + return false; } void radeon_panel_mode_fixup(struct drm_encoder *encoder, diff --git a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c index 5ff561d4e0b4..3f6343502d1f 100644 --- a/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c +++ b/trunk/drivers/gpu/drm/vmwgfx/vmwgfx_ioctl.c @@ -140,7 +140,7 @@ int vmw_present_ioctl(struct drm_device *dev, void *data, goto out_clips; } - clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL); + clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); if (clips == NULL) { DRM_ERROR("Failed to allocate clip rect list.\n"); ret = -ENOMEM; @@ -232,7 +232,7 @@ int vmw_present_readback_ioctl(struct drm_device *dev, void *data, goto out_clips; } - clips = kcalloc(num_clips, sizeof(*clips), GFP_KERNEL); + clips = kzalloc(num_clips * sizeof(*clips), GFP_KERNEL); if (clips == NULL) { DRM_ERROR("Failed to allocate clip rect list.\n"); ret = -ENOMEM; diff --git a/trunk/drivers/of/irq.c b/trunk/drivers/of/irq.c index 0f0cfa3bca30..19c0115092dd 100644 --- a/trunk/drivers/of/irq.c +++ b/trunk/drivers/of/irq.c @@ -26,6 +26,11 @@ #include #include +/* For archs that don't support NO_IRQ (such as x86), provide a dummy value */ +#ifndef NO_IRQ +#define NO_IRQ 0 +#endif + /** * irq_of_parse_and_map - Parse and map an interrupt into linux virq space * @device: Device node of the device whose interrupt is to be mapped @@ -39,7 +44,7 @@ unsigned int irq_of_parse_and_map(struct device_node *dev, int index) struct of_irq oirq; if (of_irq_map_one(dev, index, &oirq)) - return 0; + return NO_IRQ; return irq_create_of_mapping(oirq.controller, oirq.specifier, oirq.size); @@ -340,7 +345,7 @@ int of_irq_to_resource(struct device_node *dev, int index, struct resource *r) /* Only dereference the resource if both the * resource and the irq are valid. */ - if (r && irq) { + if (r && irq != NO_IRQ) { r->start = r->end = irq; r->flags = IORESOURCE_IRQ; r->name = dev->full_name; @@ -358,7 +363,7 @@ int of_irq_count(struct device_node *dev) { int nr = 0; - while (of_irq_to_resource(dev, nr, NULL)) + while (of_irq_to_resource(dev, nr, NULL) != NO_IRQ) nr++; return nr; @@ -378,7 +383,7 @@ int of_irq_to_resource_table(struct device_node *dev, struct resource *res, int i; for (i = 0; i < nr_irqs; i++, res++) - if (!of_irq_to_resource(dev, i, res)) + if (of_irq_to_resource(dev, i, res) == NO_IRQ) break; return i; diff --git a/trunk/fs/dcache.c b/trunk/fs/dcache.c index 89509b5a090e..10ba92def3f6 100644 --- a/trunk/fs/dcache.c +++ b/trunk/fs/dcache.c @@ -2439,14 +2439,16 @@ static int prepend_name(char **buffer, int *buflen, struct qstr *name) /** * prepend_path - Prepend path string to a buffer * @path: the dentry/vfsmount to report - * @root: root vfsmnt/dentry + * @root: root vfsmnt/dentry (may be modified by this function) * @buffer: pointer to the end of the buffer * @buflen: pointer to buffer length * * Caller holds the rename_lock. + * + * If path is not reachable from the supplied root, then the value of + * root is changed (without modifying refcounts). */ -static int prepend_path(const struct path *path, - const struct path *root, +static int prepend_path(const struct path *path, struct path *root, char **buffer, int *buflen) { struct dentry *dentry = path->dentry; @@ -2481,10 +2483,10 @@ static int prepend_path(const struct path *path, dentry = parent; } +out: if (!error && !slash) error = prepend(buffer, buflen, "/", 1); -out: br_read_unlock(vfsmount_lock); return error; @@ -2498,17 +2500,15 @@ static int prepend_path(const struct path *path, WARN(1, "Root dentry has weird name <%.*s>\n", (int) dentry->d_name.len, dentry->d_name.name); } - if (!slash) - error = prepend(buffer, buflen, "/", 1); - if (!error) - error = vfsmnt->mnt_ns ? 1 : 2; + root->mnt = vfsmnt; + root->dentry = dentry; goto out; } /** * __d_path - return the path of a dentry * @path: the dentry/vfsmount to report - * @root: root vfsmnt/dentry + * @root: root vfsmnt/dentry (may be modified by this function) * @buf: buffer to return value in * @buflen: buffer length * @@ -2519,10 +2519,10 @@ static int prepend_path(const struct path *path, * * "buflen" should be positive. * - * If the path is not reachable from the supplied root, return %NULL. + * If path is not reachable from the supplied root, then the value of + * root is changed (without modifying refcounts). */ -char *__d_path(const struct path *path, - const struct path *root, +char *__d_path(const struct path *path, struct path *root, char *buf, int buflen) { char *res = buf + buflen; @@ -2533,28 +2533,7 @@ char *__d_path(const struct path *path, error = prepend_path(path, root, &res, &buflen); write_sequnlock(&rename_lock); - if (error < 0) - return ERR_PTR(error); - if (error > 0) - return NULL; - return res; -} - -char *d_absolute_path(const struct path *path, - char *buf, int buflen) -{ - struct path root = {}; - char *res = buf + buflen; - int error; - - prepend(&res, &buflen, "\0", 1); - write_seqlock(&rename_lock); - error = prepend_path(path, &root, &res, &buflen); - write_sequnlock(&rename_lock); - - if (error > 1) - error = -EINVAL; - if (error < 0) + if (error) return ERR_PTR(error); return res; } @@ -2562,9 +2541,8 @@ char *d_absolute_path(const struct path *path, /* * same as __d_path but appends "(deleted)" for unlinked files. */ -static int path_with_deleted(const struct path *path, - const struct path *root, - char **buf, int *buflen) +static int path_with_deleted(const struct path *path, struct path *root, + char **buf, int *buflen) { prepend(buf, buflen, "\0", 1); if (d_unlinked(path->dentry)) { @@ -2601,6 +2579,7 @@ char *d_path(const struct path *path, char *buf, int buflen) { char *res = buf + buflen; struct path root; + struct path tmp; int error; /* @@ -2615,8 +2594,9 @@ char *d_path(const struct path *path, char *buf, int buflen) get_fs_root(current->fs, &root); write_seqlock(&rename_lock); - error = path_with_deleted(path, &root, &res, &buflen); - if (error < 0) + tmp = root; + error = path_with_deleted(path, &tmp, &res, &buflen); + if (error) res = ERR_PTR(error); write_sequnlock(&rename_lock); path_put(&root); @@ -2637,6 +2617,7 @@ char *d_path_with_unreachable(const struct path *path, char *buf, int buflen) { char *res = buf + buflen; struct path root; + struct path tmp; int error; if (path->dentry->d_op && path->dentry->d_op->d_dname) @@ -2644,8 +2625,9 @@ char *d_path_with_unreachable(const struct path *path, char *buf, int buflen) get_fs_root(current->fs, &root); write_seqlock(&rename_lock); - error = path_with_deleted(path, &root, &res, &buflen); - if (error > 0) + tmp = root; + error = path_with_deleted(path, &tmp, &res, &buflen); + if (!error && !path_equal(&tmp, &root)) error = prepend_unreachable(&res, &buflen); write_sequnlock(&rename_lock); path_put(&root); @@ -2776,18 +2758,19 @@ SYSCALL_DEFINE2(getcwd, char __user *, buf, unsigned long, size) write_seqlock(&rename_lock); if (!d_unlinked(pwd.dentry)) { unsigned long len; + struct path tmp = root; char *cwd = page + PAGE_SIZE; int buflen = PAGE_SIZE; prepend(&cwd, &buflen, "\0", 1); - error = prepend_path(&pwd, &root, &cwd, &buflen); + error = prepend_path(&pwd, &tmp, &cwd, &buflen); write_sequnlock(&rename_lock); - if (error < 0) + if (error) goto out; /* Unreachable from current root */ - if (error > 0) { + if (!path_equal(&tmp, &root)) { error = prepend_unreachable(&cwd, &buflen); if (error) goto out; diff --git a/trunk/fs/namespace.c b/trunk/fs/namespace.c index cfc6d4448aa5..6d3a1963879b 100644 --- a/trunk/fs/namespace.c +++ b/trunk/fs/namespace.c @@ -1048,12 +1048,15 @@ static int show_mountinfo(struct seq_file *m, void *v) if (err) goto out; seq_putc(m, ' '); - - /* mountpoints outside of chroot jail will give SEQ_SKIP on this */ - err = seq_path_root(m, &mnt_path, &root, " \t\n\\"); - if (err) - goto out; - + seq_path_root(m, &mnt_path, &root, " \t\n\\"); + if (root.mnt != p->root.mnt || root.dentry != p->root.dentry) { + /* + * Mountpoint is outside root, discard that one. Ugly, + * but less so than trying to do that in iterator in a + * race-free way (due to renames). + */ + return SEQ_SKIP; + } seq_puts(m, mnt->mnt_flags & MNT_READONLY ? " ro" : " rw"); show_mnt_opts(m, mnt); @@ -2773,8 +2776,3 @@ void kern_unmount(struct vfsmount *mnt) } } EXPORT_SYMBOL(kern_unmount); - -bool our_mnt(struct vfsmount *mnt) -{ - return check_mnt(mnt); -} diff --git a/trunk/fs/seq_file.c b/trunk/fs/seq_file.c index dba43c3ea3af..05d6b0e78c95 100644 --- a/trunk/fs/seq_file.c +++ b/trunk/fs/seq_file.c @@ -449,6 +449,8 @@ EXPORT_SYMBOL(seq_path); /* * Same as seq_path, but relative to supplied root. + * + * root may be changed, see __d_path(). */ int seq_path_root(struct seq_file *m, struct path *path, struct path *root, char *esc) @@ -461,8 +463,6 @@ int seq_path_root(struct seq_file *m, struct path *path, struct path *root, char *p; p = __d_path(path, root, buf, size); - if (!p) - return SEQ_SKIP; res = PTR_ERR(p); if (!IS_ERR(p)) { char *end = mangle_path(buf, p, esc); @@ -474,7 +474,7 @@ int seq_path_root(struct seq_file *m, struct path *path, struct path *root, } seq_commit(m, res); - return res < 0 && res != -ENAMETOOLONG ? res : 0; + return res < 0 ? res : 0; } /* diff --git a/trunk/include/linux/dcache.h b/trunk/include/linux/dcache.h index ed9f74f6c519..4df926199369 100644 --- a/trunk/include/linux/dcache.h +++ b/trunk/include/linux/dcache.h @@ -339,8 +339,7 @@ extern int d_validate(struct dentry *, struct dentry *); */ extern char *dynamic_dname(struct dentry *, char *, int, const char *, ...); -extern char *__d_path(const struct path *, const struct path *, char *, int); -extern char *d_absolute_path(const struct path *, char *, int); +extern char *__d_path(const struct path *path, struct path *root, char *, int); extern char *d_path(const struct path *, char *, int); extern char *d_path_with_unreachable(const struct path *, char *, int); extern char *dentry_path_raw(struct dentry *, char *, int); diff --git a/trunk/include/linux/fs.h b/trunk/include/linux/fs.h index 019dc558df1a..e3130220ce3e 100644 --- a/trunk/include/linux/fs.h +++ b/trunk/include/linux/fs.h @@ -1942,7 +1942,6 @@ extern int fd_statfs(int, struct kstatfs *); extern int statfs_by_dentry(struct dentry *, struct kstatfs *); extern int freeze_super(struct super_block *super); extern int thaw_super(struct super_block *super); -extern bool our_mnt(struct vfsmount *mnt); extern int current_umask(void); diff --git a/trunk/security/apparmor/path.c b/trunk/security/apparmor/path.c index b566eba4a65c..36cc0cc39e78 100644 --- a/trunk/security/apparmor/path.c +++ b/trunk/security/apparmor/path.c @@ -57,44 +57,23 @@ static int prepend(char **buffer, int buflen, const char *str, int namelen) static int d_namespace_path(struct path *path, char *buf, int buflen, char **name, int flags) { + struct path root, tmp; char *res; - int error = 0; - int connected = 1; - - if (path->mnt->mnt_flags & MNT_INTERNAL) { - /* it's not mounted anywhere */ - res = dentry_path(path->dentry, buf, buflen); - *name = res; - if (IS_ERR(res)) { - *name = buf; - return PTR_ERR(res); - } - if (path->dentry->d_sb->s_magic == PROC_SUPER_MAGIC && - strncmp(*name, "/sys/", 5) == 0) { - /* TODO: convert over to using a per namespace - * control instead of hard coded /proc - */ - return prepend(name, *name - buf, "/proc", 5); - } - return 0; - } + int connected, error = 0; - /* resolve paths relative to chroot?*/ + /* Get the root we want to resolve too, released below */ if (flags & PATH_CHROOT_REL) { - struct path root; + /* resolve paths relative to chroot */ get_fs_root(current->fs, &root); - res = __d_path(path, &root, buf, buflen); - if (res && !IS_ERR(res)) { - /* everything's fine */ - *name = res; - path_put(&root); - goto ok; - } - path_put(&root); - connected = 0; + } else { + /* resolve paths relative to namespace */ + root.mnt = current->nsproxy->mnt_ns->root; + root.dentry = root.mnt->mnt_root; + path_get(&root); } - res = d_absolute_path(path, buf, buflen); + tmp = root; + res = __d_path(path, &tmp, buf, buflen); *name = res; /* handle error conditions - and still allow a partial path to @@ -105,10 +84,7 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, *name = buf; goto out; } - if (!our_mnt(path->mnt)) - connected = 0; -ok: /* Handle two cases: * 1. A deleted dentry && profile is not allowing mediation of deleted * 2. On some filesystems, newly allocated dentries appear to the @@ -121,7 +97,10 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, goto out; } - /* If the path is not connected to the expected root, + /* Determine if the path is connected to the expected root */ + connected = tmp.dentry == root.dentry && tmp.mnt == root.mnt; + + /* If the path is not connected, * check if it is a sysctl and handle specially else remove any * leading / that __d_path may have returned. * Unless @@ -133,9 +112,17 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, * namespace root. */ if (!connected) { - if (!(flags & PATH_CONNECT_PATH) && + /* is the disconnect path a sysctl? */ + if (tmp.dentry->d_sb->s_magic == PROC_SUPER_MAGIC && + strncmp(*name, "/sys/", 5) == 0) { + /* TODO: convert over to using a per namespace + * control instead of hard coded /proc + */ + error = prepend(name, *name - buf, "/proc", 5); + } else if (!(flags & PATH_CONNECT_PATH) && !(((flags & CHROOT_NSCONNECT) == CHROOT_NSCONNECT) && - our_mnt(path->mnt))) { + (tmp.mnt == current->nsproxy->mnt_ns->root && + tmp.dentry == tmp.mnt->mnt_root))) { /* disconnected path, don't return pathname starting * with '/' */ @@ -146,6 +133,8 @@ static int d_namespace_path(struct path *path, char *buf, int buflen, } out: + path_put(&root); + return error; } diff --git a/trunk/security/tomoyo/realpath.c b/trunk/security/tomoyo/realpath.c index 36fa7c9bedc4..738bbdf8d4c7 100644 --- a/trunk/security/tomoyo/realpath.c +++ b/trunk/security/tomoyo/realpath.c @@ -101,8 +101,9 @@ static char *tomoyo_get_absolute_path(struct path *path, char * const buffer, { char *pos = ERR_PTR(-ENOMEM); if (buflen >= 256) { + struct path ns_root = { }; /* go to whatever namespace root we are under */ - pos = d_absolute_path(path, buffer, buflen - 1); + pos = __d_path(path, &ns_root, buffer, buflen - 1); if (!IS_ERR(pos) && *pos == '/' && pos[1]) { struct inode *inode = path->dentry->d_inode; if (inode && S_ISDIR(inode->i_mode)) {