#define SO_RCVMARK             75
 
+#define SO_PASSPIDFD           76
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64
 
 
 #define SO_RCVMARK             75
 
+#define SO_PASSPIDFD           76
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64
 
 
 #define SO_RCVMARK             0x4049
 
+#define SO_PASSPIDFD           0x404A
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64
 
 
 #define SO_RCVMARK               0x0054
 
+#define SO_PASSPIDFD             0x0055
+
 #if !defined(__KERNEL__)
 
 
 
 #define SOCK_PASSSEC           4
 #define SOCK_SUPPORT_ZC                5
 #define SOCK_CUSTOM_SOCKOPT    6
+#define SOCK_PASSPIDFD         7
 
 #ifndef ARCH_HAS_SOCKET_TYPES
 /**
 
 #define        SCM_RIGHTS      0x01            /* rw: access rights (array of int) */
 #define SCM_CREDENTIALS 0x02           /* rw: struct ucred             */
 #define SCM_SECURITY   0x03            /* rw: security label           */
+#define SCM_PIDFD      0x04            /* ro: pidfd (int)              */
 
 struct ucred {
        __u32   pid;
 
 }
 #endif /* CONFIG_SECURITY_NETWORK */
 
+static __inline__ void scm_pidfd_recv(struct msghdr *msg, struct scm_cookie *scm)
+{
+       struct file *pidfd_file = NULL;
+       int pidfd;
+
+       /*
+        * put_cmsg() doesn't return an error if CMSG is truncated,
+        * that's why we need to opencode these checks here.
+        */
+       if ((msg->msg_controllen <= sizeof(struct cmsghdr)) ||
+           (msg->msg_controllen - sizeof(struct cmsghdr)) < sizeof(int)) {
+               msg->msg_flags |= MSG_CTRUNC;
+               return;
+       }
+
+       WARN_ON_ONCE(!scm->pid);
+       pidfd = pidfd_prepare(scm->pid, 0, &pidfd_file);
+
+       if (put_cmsg(msg, SOL_SOCKET, SCM_PIDFD, sizeof(int), &pidfd)) {
+               if (pidfd_file) {
+                       put_unused_fd(pidfd);
+                       fput(pidfd_file);
+               }
+
+               return;
+       }
+
+       if (pidfd_file)
+               fd_install(pidfd, pidfd_file);
+}
+
 static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
                                struct scm_cookie *scm, int flags)
 {
        if (!msg->msg_control) {
-               if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp ||
-                   scm_has_secdata(sock))
+               if (test_bit(SOCK_PASSCRED, &sock->flags) ||
+                   test_bit(SOCK_PASSPIDFD, &sock->flags) ||
+                   scm->fp || scm_has_secdata(sock))
                        msg->msg_flags |= MSG_CTRUNC;
                scm_destroy(scm);
                return;
                put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds);
        }
 
+       if (test_bit(SOCK_PASSPIDFD, &sock->flags))
+               scm_pidfd_recv(msg, scm);
+
        scm_destroy_cred(scm);
 
        scm_passec(sock, msg, scm);
 
 
 #define SO_RCVMARK             75
 
+#define SO_PASSPIDFD           76
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
 
                        clear_bit(SOCK_PASSCRED, &sock->flags);
                break;
 
+       case SO_PASSPIDFD:
+               if (valbool)
+                       set_bit(SOCK_PASSPIDFD, &sock->flags);
+               else
+                       clear_bit(SOCK_PASSPIDFD, &sock->flags);
+               break;
+
        case SO_TIMESTAMP_OLD:
        case SO_TIMESTAMP_NEW:
        case SO_TIMESTAMPNS_OLD:
                v.val = !!test_bit(SOCK_PASSCRED, &sock->flags);
                break;
 
+       case SO_PASSPIDFD:
+               v.val = !!test_bit(SOCK_PASSPIDFD, &sock->flags);
+               break;
+
        case SO_PEERCRED:
        {
                struct ucred peercred;
 
        case SO_BROADCAST:
        case SO_BSDCOMPAT:
        case SO_PASSCRED:
+       case SO_PASSPIDFD:
        case SO_PASSSEC:
        case SO_RXQ_OVFL:
        case SO_WIFI_STATUS:
 
                if (err)
                        goto out;
 
-               if (test_bit(SOCK_PASSCRED, &sock->flags) &&
+               if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
+                    test_bit(SOCK_PASSPIDFD, &sock->flags)) &&
                    !unix_sk(sk)->addr) {
                        err = unix_autobind(sk);
                        if (err)
        if (err)
                goto out;
 
-       if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr) {
+       if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
+            test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) {
                err = unix_autobind(sk);
                if (err)
                        goto out;
 {
        if (test_bit(SOCK_PASSCRED, &old->flags))
                set_bit(SOCK_PASSCRED, &new->flags);
+       if (test_bit(SOCK_PASSPIDFD, &old->flags))
+               set_bit(SOCK_PASSPIDFD, &new->flags);
        if (test_bit(SOCK_PASSSEC, &old->flags))
                set_bit(SOCK_PASSSEC, &new->flags);
 }
                                  const struct sock *other)
 {
        return test_bit(SOCK_PASSCRED, &sock->flags) ||
+              test_bit(SOCK_PASSPIDFD, &sock->flags) ||
               !other->sk_socket ||
-              test_bit(SOCK_PASSCRED, &other->sk_socket->flags);
+              test_bit(SOCK_PASSCRED, &other->sk_socket->flags) ||
+              test_bit(SOCK_PASSPIDFD, &other->sk_socket->flags);
 }
 
 /*
                        goto out;
        }
 
-       if (test_bit(SOCK_PASSCRED, &sock->flags) && !u->addr) {
+       if ((test_bit(SOCK_PASSCRED, &sock->flags) ||
+            test_bit(SOCK_PASSPIDFD, &sock->flags)) && !u->addr) {
                err = unix_autobind(sk);
                if (err)
                        goto out;
                        /* Never glue messages from different writers */
                        if (!unix_skb_scm_eq(skb, &scm))
                                break;
-               } else if (test_bit(SOCK_PASSCRED, &sock->flags)) {
+               } else if (test_bit(SOCK_PASSCRED, &sock->flags) ||
+                          test_bit(SOCK_PASSPIDFD, &sock->flags)) {
                        /* Copy credentials */
                        scm_set_cred(&scm, UNIXCB(skb).pid, UNIXCB(skb).uid, UNIXCB(skb).gid);
                        unix_set_secdata(&scm, skb);
 
 
 #define SO_RCVMARK             75
 
+#define SO_PASSPIDFD           76
+
 #if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))