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