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