xref: /openbmc/linux/include/net/scm.h (revision 257b5358b32f17e0603b6ff57b13610b0e02348f)
11da177e4SLinus Torvalds #ifndef __LINUX_NET_SCM_H
21da177e4SLinus Torvalds #define __LINUX_NET_SCM_H
31da177e4SLinus Torvalds 
41da177e4SLinus Torvalds #include <linux/limits.h>
51da177e4SLinus Torvalds #include <linux/net.h>
6dc49c1f9SCatherine Zhang #include <linux/security.h>
7b488893aSPavel Emelyanov #include <linux/pid.h>
8b488893aSPavel Emelyanov #include <linux/nsproxy.h>
91da177e4SLinus Torvalds 
101da177e4SLinus Torvalds /* Well, we should have at least one descriptor open
111da177e4SLinus Torvalds  * to accept passed FDs 8)
121da177e4SLinus Torvalds  */
13c09edd6eSRoland McGrath #define SCM_MAX_FD	255
141da177e4SLinus Torvalds 
15fd2c3ef7SEric Dumazet struct scm_fp_list {
16f8d570a4SDavid Miller 	struct list_head	list;
171da177e4SLinus Torvalds 	int			count;
181da177e4SLinus Torvalds 	struct file		*fp[SCM_MAX_FD];
191da177e4SLinus Torvalds };
201da177e4SLinus Torvalds 
21fd2c3ef7SEric Dumazet struct scm_cookie {
22*257b5358SEric W. Biederman 	struct pid		*pid;		/* Skb credentials */
23*257b5358SEric W. Biederman 	const struct cred	*cred;
241da177e4SLinus Torvalds 	struct scm_fp_list	*fp;		/* Passed files		*/
25812e876eSEric W. Biederman 	struct ucred		creds;		/* Skb credentials	*/
26877ce7c1SCatherine Zhang #ifdef CONFIG_SECURITY_NETWORK
27dc49c1f9SCatherine Zhang 	u32			secid;		/* Passed security ID 	*/
28877ce7c1SCatherine Zhang #endif
291da177e4SLinus Torvalds };
301da177e4SLinus Torvalds 
311da177e4SLinus Torvalds extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
321da177e4SLinus Torvalds extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
331da177e4SLinus Torvalds extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
341da177e4SLinus Torvalds extern void __scm_destroy(struct scm_cookie *scm);
351da177e4SLinus Torvalds extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
361da177e4SLinus Torvalds 
37dc49c1f9SCatherine Zhang #ifdef CONFIG_SECURITY_NETWORK
38dc49c1f9SCatherine Zhang static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
39dc49c1f9SCatherine Zhang {
40dc49c1f9SCatherine Zhang 	security_socket_getpeersec_dgram(sock, NULL, &scm->secid);
41dc49c1f9SCatherine Zhang }
42dc49c1f9SCatherine Zhang #else
43dc49c1f9SCatherine Zhang static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
44dc49c1f9SCatherine Zhang { }
45dc49c1f9SCatherine Zhang #endif /* CONFIG_SECURITY_NETWORK */
46dc49c1f9SCatherine Zhang 
47*257b5358SEric W. Biederman static __inline__ void scm_set_cred(struct scm_cookie *scm,
48*257b5358SEric W. Biederman 				    struct pid *pid, const struct cred *cred)
49*257b5358SEric W. Biederman {
50*257b5358SEric W. Biederman 	scm->pid  = get_pid(pid);
51*257b5358SEric W. Biederman 	scm->cred = get_cred(cred);
52*257b5358SEric W. Biederman 	cred_to_ucred(pid, cred, &scm->creds);
53*257b5358SEric W. Biederman }
54*257b5358SEric W. Biederman 
55*257b5358SEric W. Biederman static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
56*257b5358SEric W. Biederman {
57*257b5358SEric W. Biederman 	put_pid(scm->pid);
58*257b5358SEric W. Biederman 	scm->pid  = NULL;
59*257b5358SEric W. Biederman 
60*257b5358SEric W. Biederman 	if (scm->cred)
61*257b5358SEric W. Biederman 		put_cred(scm->cred);
62*257b5358SEric W. Biederman 	scm->cred = NULL;
63*257b5358SEric W. Biederman }
64*257b5358SEric W. Biederman 
651da177e4SLinus Torvalds static __inline__ void scm_destroy(struct scm_cookie *scm)
661da177e4SLinus Torvalds {
67*257b5358SEric W. Biederman 	scm_destroy_cred(scm);
681da177e4SLinus Torvalds 	if (scm && scm->fp)
691da177e4SLinus Torvalds 		__scm_destroy(scm);
701da177e4SLinus Torvalds }
711da177e4SLinus Torvalds 
721da177e4SLinus Torvalds static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
731da177e4SLinus Torvalds 			       struct scm_cookie *scm)
741da177e4SLinus Torvalds {
75*257b5358SEric W. Biederman 	scm_set_cred(scm, task_tgid(current), current_cred());
761d541dddSBenjamin LaHaise 	scm->fp = NULL;
77dc49c1f9SCatherine Zhang 	unix_get_peersec_dgram(sock, scm);
781da177e4SLinus Torvalds 	if (msg->msg_controllen <= 0)
791da177e4SLinus Torvalds 		return 0;
801da177e4SLinus Torvalds 	return __scm_send(sock, msg, scm);
811da177e4SLinus Torvalds }
821da177e4SLinus Torvalds 
83877ce7c1SCatherine Zhang #ifdef CONFIG_SECURITY_NETWORK
84877ce7c1SCatherine Zhang static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
85877ce7c1SCatherine Zhang {
86dc49c1f9SCatherine Zhang 	char *secdata;
87dc49c1f9SCatherine Zhang 	u32 seclen;
88dc49c1f9SCatherine Zhang 	int err;
89dc49c1f9SCatherine Zhang 
90dc49c1f9SCatherine Zhang 	if (test_bit(SOCK_PASSSEC, &sock->flags)) {
91dc49c1f9SCatherine Zhang 		err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
92dc49c1f9SCatherine Zhang 
93dc49c1f9SCatherine Zhang 		if (!err) {
94dc49c1f9SCatherine Zhang 			put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
95dc49c1f9SCatherine Zhang 			security_release_secctx(secdata, seclen);
96dc49c1f9SCatherine Zhang 		}
97dc49c1f9SCatherine Zhang 	}
98877ce7c1SCatherine Zhang }
99877ce7c1SCatherine Zhang #else
100877ce7c1SCatherine Zhang static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
101877ce7c1SCatherine Zhang { }
102877ce7c1SCatherine Zhang #endif /* CONFIG_SECURITY_NETWORK */
103877ce7c1SCatherine Zhang 
1041da177e4SLinus Torvalds static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
1051da177e4SLinus Torvalds 				struct scm_cookie *scm, int flags)
1061da177e4SLinus Torvalds {
107fd2c3ef7SEric Dumazet 	if (!msg->msg_control) {
1081da177e4SLinus Torvalds 		if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
1091da177e4SLinus Torvalds 			msg->msg_flags |= MSG_CTRUNC;
1101da177e4SLinus Torvalds 		scm_destroy(scm);
1111da177e4SLinus Torvalds 		return;
1121da177e4SLinus Torvalds 	}
1131da177e4SLinus Torvalds 
1141da177e4SLinus Torvalds 	if (test_bit(SOCK_PASSCRED, &sock->flags))
1151da177e4SLinus Torvalds 		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
1161da177e4SLinus Torvalds 
117*257b5358SEric W. Biederman 	scm_destroy_cred(scm);
118*257b5358SEric W. Biederman 
119877ce7c1SCatherine Zhang 	scm_passec(sock, msg, scm);
120877ce7c1SCatherine Zhang 
1211da177e4SLinus Torvalds 	if (!scm->fp)
1221da177e4SLinus Torvalds 		return;
1231da177e4SLinus Torvalds 
1241da177e4SLinus Torvalds 	scm_detach_fds(msg, scm);
1251da177e4SLinus Torvalds }
1261da177e4SLinus Torvalds 
1271da177e4SLinus Torvalds 
1281da177e4SLinus Torvalds #endif /* __LINUX_NET_SCM_H */
1291da177e4SLinus Torvalds 
130