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