};
 
 struct scm_cookie {
+       struct pid              *pid;           /* Skb credentials */
+       const struct cred       *cred;
        struct scm_fp_list      *fp;            /* Passed files         */
        struct ucred            creds;          /* Skb credentials      */
 #ifdef CONFIG_SECURITY_NETWORK
 { }
 #endif /* CONFIG_SECURITY_NETWORK */
 
+static __inline__ void scm_set_cred(struct scm_cookie *scm,
+                                   struct pid *pid, const struct cred *cred)
+{
+       scm->pid  = get_pid(pid);
+       scm->cred = get_cred(cred);
+       cred_to_ucred(pid, cred, &scm->creds);
+}
+
+static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
+{
+       put_pid(scm->pid);
+       scm->pid  = NULL;
+
+       if (scm->cred)
+               put_cred(scm->cred);
+       scm->cred = NULL;
+}
+
 static __inline__ void scm_destroy(struct scm_cookie *scm)
 {
+       scm_destroy_cred(scm);
        if (scm && scm->fp)
                __scm_destroy(scm);
 }
 static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
                               struct scm_cookie *scm)
 {
-       struct task_struct *p = current;
-       scm->creds.uid = current_uid();
-       scm->creds.gid = current_gid();
-       scm->creds.pid = task_tgid_vnr(p);
+       scm_set_cred(scm, task_tgid(current), current_cred());
        scm->fp = NULL;
        unix_get_peersec_dgram(sock, scm);
        if (msg->msg_controllen <= 0)
        if (test_bit(SOCK_PASSCRED, &sock->flags))
                put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
 
+       scm_destroy_cred(scm);
+
        scm_passec(sock, msg, scm);
 
        if (!scm->fp)
 
                        err = scm_check_creds(&p->creds);
                        if (err)
                                goto error;
+
+                       if (pid_vnr(p->pid) != p->creds.pid) {
+                               struct pid *pid;
+                               err = -ESRCH;
+                               pid = find_get_pid(p->creds.pid);
+                               if (!pid)
+                                       goto error;
+                               put_pid(p->pid);
+                               p->pid = pid;
+                       }
+
+                       if ((p->cred->euid != p->creds.uid) ||
+                               (p->cred->egid != p->creds.gid)) {
+                               struct cred *cred;
+                               err = -ENOMEM;
+                               cred = prepare_creds();
+                               if (!cred)
+                                       goto error;
+
+                               cred->uid = cred->euid = p->creds.uid;
+                               cred->gid = cred->egid = p->creds.uid;
+                               put_cred(p->cred);
+                               p->cred = cred;
+                       }
                        break;
                default:
                        goto error;