linux/include/net/scm.h
<<
>>
Prefs
   1#ifndef __LINUX_NET_SCM_H
   2#define __LINUX_NET_SCM_H
   3
   4#include <linux/limits.h>
   5#include <linux/net.h>
   6#include <linux/security.h>
   7#include <linux/pid.h>
   8#include <linux/nsproxy.h>
   9
  10/* Well, we should have at least one descriptor open
  11 * to accept passed FDs 8)
  12 */
  13#define SCM_MAX_FD      253
  14
  15struct scm_creds {
  16        u32     pid;
  17        kuid_t  uid;
  18        kgid_t  gid;
  19};
  20
  21struct scm_fp_list {
  22        short                   count;
  23        short                   max;
  24        struct file             *fp[SCM_MAX_FD];
  25};
  26
  27struct scm_cookie {
  28        struct pid              *pid;           /* Skb credentials */
  29        struct scm_fp_list      *fp;            /* Passed files         */
  30        struct scm_creds        creds;          /* Skb credentials      */
  31#ifdef CONFIG_SECURITY_NETWORK
  32        u32                     secid;          /* Passed security ID   */
  33#endif
  34};
  35
  36void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
  37void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
  38int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
  39void __scm_destroy(struct scm_cookie *scm);
  40struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl);
  41
  42#ifdef CONFIG_SECURITY_NETWORK
  43static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
  44{
  45        security_socket_getpeersec_dgram(sock, NULL, &scm->secid);
  46}
  47#else
  48static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
  49{ }
  50#endif /* CONFIG_SECURITY_NETWORK */
  51
  52static __inline__ void scm_set_cred(struct scm_cookie *scm,
  53                                    struct pid *pid, kuid_t uid, kgid_t gid)
  54{
  55        scm->pid  = get_pid(pid);
  56        scm->creds.pid = pid_vnr(pid);
  57        scm->creds.uid = uid;
  58        scm->creds.gid = gid;
  59}
  60
  61static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
  62{
  63        put_pid(scm->pid);
  64        scm->pid  = NULL;
  65}
  66
  67static __inline__ void scm_destroy(struct scm_cookie *scm)
  68{
  69        scm_destroy_cred(scm);
  70        if (scm->fp)
  71                __scm_destroy(scm);
  72}
  73
  74static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
  75                               struct scm_cookie *scm, bool forcecreds)
  76{
  77        memset(scm, 0, sizeof(*scm));
  78        scm->creds.uid = INVALID_UID;
  79        scm->creds.gid = INVALID_GID;
  80        if (forcecreds)
  81                scm_set_cred(scm, task_tgid(current), current_uid(), current_gid());
  82        unix_get_peersec_dgram(sock, scm);
  83        if (msg->msg_controllen <= 0)
  84                return 0;
  85        return __scm_send(sock, msg, scm);
  86}
  87
  88#ifdef CONFIG_SECURITY_NETWORK
  89static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
  90{
  91        char *secdata;
  92        u32 seclen;
  93        int err;
  94
  95        if (test_bit(SOCK_PASSSEC, &sock->flags)) {
  96                err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
  97
  98                if (!err) {
  99                        put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
 100                        security_release_secctx(secdata, seclen);
 101                }
 102        }
 103}
 104#else
 105static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
 106{ }
 107#endif /* CONFIG_SECURITY_NETWORK */
 108
 109static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
 110                                struct scm_cookie *scm, int flags)
 111{
 112        if (!msg->msg_control) {
 113                if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
 114                        msg->msg_flags |= MSG_CTRUNC;
 115                scm_destroy(scm);
 116                return;
 117        }
 118
 119        if (test_bit(SOCK_PASSCRED, &sock->flags)) {
 120                struct user_namespace *current_ns = current_user_ns();
 121                struct ucred ucreds = {
 122                        .pid = scm->creds.pid,
 123                        .uid = from_kuid_munged(current_ns, scm->creds.uid),
 124                        .gid = from_kgid_munged(current_ns, scm->creds.gid),
 125                };
 126                put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds);
 127        }
 128
 129        scm_destroy_cred(scm);
 130
 131        scm_passec(sock, msg, scm);
 132
 133        if (!scm->fp)
 134                return;
 135        
 136        scm_detach_fds(msg, scm);
 137}
 138
 139
 140#endif /* __LINUX_NET_SCM_H */
 141
 142