Back to home page

OSCL-LXR

 
 

    


0001 /* SPDX-License-Identifier: GPL-2.0 */
0002 #ifndef __LINUX_NET_SCM_H
0003 #define __LINUX_NET_SCM_H
0004 
0005 #include <linux/limits.h>
0006 #include <linux/net.h>
0007 #include <linux/cred.h>
0008 #include <linux/security.h>
0009 #include <linux/pid.h>
0010 #include <linux/nsproxy.h>
0011 #include <linux/sched/signal.h>
0012 
0013 /* Well, we should have at least one descriptor open
0014  * to accept passed FDs 8)
0015  */
0016 #define SCM_MAX_FD  253
0017 
0018 struct scm_creds {
0019     u32 pid;
0020     kuid_t  uid;
0021     kgid_t  gid;
0022 };
0023 
0024 struct scm_fp_list {
0025     short           count;
0026     short           max;
0027     struct user_struct  *user;
0028     struct file     *fp[SCM_MAX_FD];
0029 };
0030 
0031 struct scm_cookie {
0032     struct pid      *pid;       /* Skb credentials */
0033     struct scm_fp_list  *fp;        /* Passed files     */
0034     struct scm_creds    creds;      /* Skb credentials  */
0035 #ifdef CONFIG_SECURITY_NETWORK
0036     u32         secid;      /* Passed security ID   */
0037 #endif
0038 };
0039 
0040 void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
0041 void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
0042 int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
0043 void __scm_destroy(struct scm_cookie *scm);
0044 struct scm_fp_list *scm_fp_dup(struct scm_fp_list *fpl);
0045 
0046 #ifdef CONFIG_SECURITY_NETWORK
0047 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
0048 {
0049     security_socket_getpeersec_dgram(sock, NULL, &scm->secid);
0050 }
0051 #else
0052 static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
0053 { }
0054 #endif /* CONFIG_SECURITY_NETWORK */
0055 
0056 static __inline__ void scm_set_cred(struct scm_cookie *scm,
0057                     struct pid *pid, kuid_t uid, kgid_t gid)
0058 {
0059     scm->pid  = get_pid(pid);
0060     scm->creds.pid = pid_vnr(pid);
0061     scm->creds.uid = uid;
0062     scm->creds.gid = gid;
0063 }
0064 
0065 static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
0066 {
0067     put_pid(scm->pid);
0068     scm->pid  = NULL;
0069 }
0070 
0071 static __inline__ void scm_destroy(struct scm_cookie *scm)
0072 {
0073     scm_destroy_cred(scm);
0074     if (scm->fp)
0075         __scm_destroy(scm);
0076 }
0077 
0078 static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
0079                    struct scm_cookie *scm, bool forcecreds)
0080 {
0081     memset(scm, 0, sizeof(*scm));
0082     scm->creds.uid = INVALID_UID;
0083     scm->creds.gid = INVALID_GID;
0084     if (forcecreds)
0085         scm_set_cred(scm, task_tgid(current), current_uid(), current_gid());
0086     unix_get_peersec_dgram(sock, scm);
0087     if (msg->msg_controllen <= 0)
0088         return 0;
0089     return __scm_send(sock, msg, scm);
0090 }
0091 
0092 #ifdef CONFIG_SECURITY_NETWORK
0093 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
0094 {
0095     char *secdata;
0096     u32 seclen;
0097     int err;
0098 
0099     if (test_bit(SOCK_PASSSEC, &sock->flags)) {
0100         err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
0101 
0102         if (!err) {
0103             put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
0104             security_release_secctx(secdata, seclen);
0105         }
0106     }
0107 }
0108 #else
0109 static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
0110 { }
0111 #endif /* CONFIG_SECURITY_NETWORK */
0112 
0113 static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
0114                 struct scm_cookie *scm, int flags)
0115 {
0116     if (!msg->msg_control) {
0117         if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
0118             msg->msg_flags |= MSG_CTRUNC;
0119         scm_destroy(scm);
0120         return;
0121     }
0122 
0123     if (test_bit(SOCK_PASSCRED, &sock->flags)) {
0124         struct user_namespace *current_ns = current_user_ns();
0125         struct ucred ucreds = {
0126             .pid = scm->creds.pid,
0127             .uid = from_kuid_munged(current_ns, scm->creds.uid),
0128             .gid = from_kgid_munged(current_ns, scm->creds.gid),
0129         };
0130         put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(ucreds), &ucreds);
0131     }
0132 
0133     scm_destroy_cred(scm);
0134 
0135     scm_passec(sock, msg, scm);
0136 
0137     if (!scm->fp)
0138         return;
0139     
0140     scm_detach_fds(msg, scm);
0141 }
0142 
0143 
0144 #endif /* __LINUX_NET_SCM_H */
0145