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