Merge commit 'v3.5-rc2' into next
authorJames Morris <james.l.morris@oracle.com>
Sun, 10 Jun 2012 12:52:10 +0000 (22:52 +1000)
committerJames Morris <james.l.morris@oracle.com>
Sun, 10 Jun 2012 12:52:10 +0000 (22:52 +1000)
1  2 
lib/Kconfig
security/keys/compat.c
security/keys/internal.h
security/keys/keyctl.c

diff --combined lib/Kconfig
@@@ -16,6 -16,12 +16,12 @@@ config BITREVERS
  config RATIONAL
        boolean
  
+ config GENERIC_STRNCPY_FROM_USER
+       bool
+ config GENERIC_STRNLEN_USER
+       bool
  config GENERIC_FIND_FIRST_BIT
        bool
  
@@@ -33,6 -39,9 +39,9 @@@ config GENERIC_I
        boolean
        default n
  
+ config STMP_DEVICE
+       bool
  config CRC_CCITT
        tristate "CRC-CCITT functions"
        help
@@@ -353,6 -362,14 +362,14 @@@ config CORDI
          This option provides an implementation of the CORDIC algorithm;
          calculations are in fixed point. Module will be called cordic.
  
+ config DDR
+       bool "JEDEC DDR data"
+       help
+         Data from JEDEC specs for DDR SDRAM memories,
+         particularly the AC timing parameters and addressing
+         information. This data is useful for drivers handling
+         DDR SDRAM controllers.
  config MPILIB
        tristate
        select CLZ_TAB
          It is used to implement RSA digital signature verification,
          which is used by IMA/EVM digital signature extension.
  
 -config MPILIB_EXTRA
 -      bool
 -      depends on MPILIB
 -      help
 -        Additional sources of multiprecision maths library from GnuPG.
 -        This code is unnecessary for RSA digital signature verification,
 -        but can be compiled if needed.
 -
  config SIGNATURE
        tristate
        depends on KEYS && CRYPTO
diff --combined security/keys/compat.c
@@@ -24,7 -24,7 +24,7 @@@
   *
   * If successful, 0 will be returned.
   */
 -long compat_keyctl_instantiate_key_iov(
 +static long compat_keyctl_instantiate_key_iov(
        key_serial_t id,
        const struct compat_iovec __user *_payload_iov,
        unsigned ioc,
        struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
        long ret;
  
 -      if (_payload_iov == 0 || ioc == 0)
 +      if (!_payload_iov || !ioc)
                goto no_payload;
  
        ret = compat_rw_copy_check_uvector(WRITE, _payload_iov, ioc,
                                           ARRAY_SIZE(iovstack),
-                                          iovstack, &iov, 1);
+                                          iovstack, &iov);
        if (ret < 0)
                return ret;
        if (ret == 0)
diff --combined security/keys/internal.h
@@@ -14,6 -14,7 +14,7 @@@
  
  #include <linux/sched.h>
  #include <linux/key-type.h>
+ #include <linux/task_work.h>
  
  #ifdef __KDEBUG
  #define kenter(FMT, ...) \
@@@ -148,6 -149,7 +149,7 @@@ extern key_ref_t lookup_user_key(key_se
  #define KEY_LOOKUP_FOR_UNLINK 0x04
  
  extern long join_session_keyring(const char *name);
+ extern void key_change_session_keyring(struct task_work *twork);
  
  extern struct work_struct key_gc_work;
  extern unsigned key_gc_delay;
@@@ -240,7 -242,7 +242,7 @@@ extern long keyctl_instantiate_key_iov(
  extern long keyctl_invalidate_key(key_serial_t);
  
  extern long keyctl_instantiate_key_common(key_serial_t,
 -                                        const struct iovec __user *,
 +                                        const struct iovec *,
                                          unsigned, size_t, key_serial_t);
  
  /*
diff --combined security/keys/keyctl.c
@@@ -84,7 -84,7 +84,7 @@@ SYSCALL_DEFINE5(add_key, const char __u
        vm = false;
        if (_payload) {
                ret = -ENOMEM;
-               payload = kmalloc(plen, GFP_KERNEL);
+               payload = kmalloc(plen, GFP_KERNEL | __GFP_NOWARN);
                if (!payload) {
                        if (plen <= PAGE_SIZE)
                                goto error2;
@@@ -1106,11 -1106,11 +1106,11 @@@ long keyctl_instantiate_key_iov(key_ser
        struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;
        long ret;
  
 -      if (_payload_iov == 0 || ioc == 0)
 +      if (!_payload_iov || !ioc)
                goto no_payload;
  
        ret = rw_copy_check_uvector(WRITE, _payload_iov, ioc,
-                                   ARRAY_SIZE(iovstack), iovstack, &iov, 1);
+                                   ARRAY_SIZE(iovstack), iovstack, &iov);
        if (ret < 0)
                return ret;
        if (ret == 0)
@@@ -1454,50 -1454,57 +1454,57 @@@ long keyctl_get_security(key_serial_t k
   */
  long keyctl_session_to_parent(void)
  {
- #ifdef TIF_NOTIFY_RESUME
        struct task_struct *me, *parent;
        const struct cred *mycred, *pcred;
-       struct cred *cred, *oldcred;
+       struct task_work *newwork, *oldwork;
        key_ref_t keyring_r;
+       struct cred *cred;
        int ret;
  
        keyring_r = lookup_user_key(KEY_SPEC_SESSION_KEYRING, 0, KEY_LINK);
        if (IS_ERR(keyring_r))
                return PTR_ERR(keyring_r);
  
+       ret = -ENOMEM;
+       newwork = kmalloc(sizeof(struct task_work), GFP_KERNEL);
+       if (!newwork)
+               goto error_keyring;
        /* our parent is going to need a new cred struct, a new tgcred struct
         * and new security data, so we allocate them here to prevent ENOMEM in
         * our parent */
-       ret = -ENOMEM;
        cred = cred_alloc_blank();
        if (!cred)
-               goto error_keyring;
+               goto error_newwork;
  
        cred->tgcred->session_keyring = key_ref_to_ptr(keyring_r);
-       keyring_r = NULL;
+       init_task_work(newwork, key_change_session_keyring, cred);
  
        me = current;
        rcu_read_lock();
        write_lock_irq(&tasklist_lock);
  
-       parent = me->real_parent;
        ret = -EPERM;
+       oldwork = NULL;
+       parent = me->real_parent;
  
        /* the parent mustn't be init and mustn't be a kernel thread */
        if (parent->pid <= 1 || !parent->mm)
-               goto not_permitted;
+               goto unlock;
  
        /* the parent must be single threaded */
        if (!thread_group_empty(parent))
-               goto not_permitted;
+               goto unlock;
  
        /* the parent and the child must have different session keyrings or
         * there's no point */
        mycred = current_cred();
        pcred = __task_cred(parent);
        if (mycred == pcred ||
-           mycred->tgcred->session_keyring == pcred->tgcred->session_keyring)
-               goto already_same;
+           mycred->tgcred->session_keyring == pcred->tgcred->session_keyring) {
+               ret = 0;
+               goto unlock;
+       }
  
        /* the parent must have the same effective ownership and mustn't be
         * SUID/SGID */
            pcred->gid  != mycred->egid ||
            pcred->egid != mycred->egid ||
            pcred->sgid != mycred->egid)
-               goto not_permitted;
+               goto unlock;
  
        /* the keyrings must have the same UID */
        if ((pcred->tgcred->session_keyring &&
             pcred->tgcred->session_keyring->uid != mycred->euid) ||
            mycred->tgcred->session_keyring->uid != mycred->euid)
-               goto not_permitted;
+               goto unlock;
  
-       /* if there's an already pending keyring replacement, then we replace
-        * that */
-       oldcred = parent->replacement_session_keyring;
+       /* cancel an already pending keyring replacement */
+       oldwork = task_work_cancel(parent, key_change_session_keyring);
  
        /* the replacement session keyring is applied just prior to userspace
         * restarting */
-       parent->replacement_session_keyring = cred;
-       cred = NULL;
-       set_ti_thread_flag(task_thread_info(parent), TIF_NOTIFY_RESUME);
-       write_unlock_irq(&tasklist_lock);
-       rcu_read_unlock();
-       if (oldcred)
-               put_cred(oldcred);
-       return 0;
- already_same:
-       ret = 0;
- not_permitted:
+       ret = task_work_add(parent, newwork, true);
+       if (!ret)
+               newwork = NULL;
+ unlock:
        write_unlock_irq(&tasklist_lock);
        rcu_read_unlock();
-       put_cred(cred);
+       if (oldwork) {
+               put_cred(oldwork->data);
+               kfree(oldwork);
+       }
+       if (newwork) {
+               put_cred(newwork->data);
+               kfree(newwork);
+       }
        return ret;
  
+ error_newwork:
+       kfree(newwork);
  error_keyring:
        key_ref_put(keyring_r);
        return ret;
- #else /* !TIF_NOTIFY_RESUME */
-       /*
-        * To be removed when TIF_NOTIFY_RESUME has been implemented on
-        * m68k/xtensa
-        */
- #warning TIF_NOTIFY_RESUME not implemented
-       return -EOPNOTSUPP;
- #endif /* !TIF_NOTIFY_RESUME */
  }
  
  /*