xref: /openbmc/linux/include/net/scm.h (revision bba14de98753cb6599a2dae0e520714b2153522d)
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  */
13*bba14de9SEric Dumazet #define SCM_MAX_FD	253
141da177e4SLinus Torvalds 
15fd2c3ef7SEric Dumazet struct scm_fp_list {
16f8d570a4SDavid Miller 	struct list_head	list;
17*bba14de9SEric Dumazet 	short			count;
18*bba14de9SEric Dumazet 	short			max;
191da177e4SLinus Torvalds 	struct file		*fp[SCM_MAX_FD];
201da177e4SLinus Torvalds };
211da177e4SLinus Torvalds 
22fd2c3ef7SEric Dumazet struct scm_cookie {
23257b5358SEric W. Biederman 	struct pid		*pid;		/* Skb credentials */
24257b5358SEric W. Biederman 	const struct cred	*cred;
251da177e4SLinus Torvalds 	struct scm_fp_list	*fp;		/* Passed files		*/
26812e876eSEric W. Biederman 	struct ucred		creds;		/* Skb credentials	*/
27877ce7c1SCatherine Zhang #ifdef CONFIG_SECURITY_NETWORK
28dc49c1f9SCatherine Zhang 	u32			secid;		/* Passed security ID 	*/
29877ce7c1SCatherine Zhang #endif
301da177e4SLinus Torvalds };
311da177e4SLinus Torvalds 
321da177e4SLinus Torvalds extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
331da177e4SLinus Torvalds extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
341da177e4SLinus Torvalds extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
351da177e4SLinus Torvalds extern void __scm_destroy(struct scm_cookie *scm);
361da177e4SLinus Torvalds extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
371da177e4SLinus Torvalds 
38dc49c1f9SCatherine Zhang #ifdef CONFIG_SECURITY_NETWORK
39dc49c1f9SCatherine Zhang static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
40dc49c1f9SCatherine Zhang {
41dc49c1f9SCatherine Zhang 	security_socket_getpeersec_dgram(sock, NULL, &scm->secid);
42dc49c1f9SCatherine Zhang }
43dc49c1f9SCatherine Zhang #else
44dc49c1f9SCatherine Zhang static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
45dc49c1f9SCatherine Zhang { }
46dc49c1f9SCatherine Zhang #endif /* CONFIG_SECURITY_NETWORK */
47dc49c1f9SCatherine Zhang 
48257b5358SEric W. Biederman static __inline__ void scm_set_cred(struct scm_cookie *scm,
49257b5358SEric W. Biederman 				    struct pid *pid, const struct cred *cred)
50257b5358SEric W. Biederman {
51257b5358SEric W. Biederman 	scm->pid  = get_pid(pid);
52257b5358SEric W. Biederman 	scm->cred = get_cred(cred);
53257b5358SEric W. Biederman 	cred_to_ucred(pid, cred, &scm->creds);
54257b5358SEric W. Biederman }
55257b5358SEric W. Biederman 
56257b5358SEric W. Biederman static __inline__ void scm_destroy_cred(struct scm_cookie *scm)
57257b5358SEric W. Biederman {
58257b5358SEric W. Biederman 	put_pid(scm->pid);
59257b5358SEric W. Biederman 	scm->pid  = NULL;
60257b5358SEric W. Biederman 
61257b5358SEric W. Biederman 	if (scm->cred)
62257b5358SEric W. Biederman 		put_cred(scm->cred);
63257b5358SEric W. Biederman 	scm->cred = NULL;
64257b5358SEric W. Biederman }
65257b5358SEric W. Biederman 
661da177e4SLinus Torvalds static __inline__ void scm_destroy(struct scm_cookie *scm)
671da177e4SLinus Torvalds {
68257b5358SEric W. Biederman 	scm_destroy_cred(scm);
691da177e4SLinus Torvalds 	if (scm && scm->fp)
701da177e4SLinus Torvalds 		__scm_destroy(scm);
711da177e4SLinus Torvalds }
721da177e4SLinus Torvalds 
731da177e4SLinus Torvalds static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
741da177e4SLinus Torvalds 			       struct scm_cookie *scm)
751da177e4SLinus Torvalds {
76257b5358SEric W. Biederman 	scm_set_cred(scm, task_tgid(current), current_cred());
771d541dddSBenjamin LaHaise 	scm->fp = NULL;
78dc49c1f9SCatherine Zhang 	unix_get_peersec_dgram(sock, scm);
791da177e4SLinus Torvalds 	if (msg->msg_controllen <= 0)
801da177e4SLinus Torvalds 		return 0;
811da177e4SLinus Torvalds 	return __scm_send(sock, msg, scm);
821da177e4SLinus Torvalds }
831da177e4SLinus Torvalds 
84877ce7c1SCatherine Zhang #ifdef CONFIG_SECURITY_NETWORK
85877ce7c1SCatherine Zhang static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
86877ce7c1SCatherine Zhang {
87dc49c1f9SCatherine Zhang 	char *secdata;
88dc49c1f9SCatherine Zhang 	u32 seclen;
89dc49c1f9SCatherine Zhang 	int err;
90dc49c1f9SCatherine Zhang 
91dc49c1f9SCatherine Zhang 	if (test_bit(SOCK_PASSSEC, &sock->flags)) {
92dc49c1f9SCatherine Zhang 		err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
93dc49c1f9SCatherine Zhang 
94dc49c1f9SCatherine Zhang 		if (!err) {
95dc49c1f9SCatherine Zhang 			put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
96dc49c1f9SCatherine Zhang 			security_release_secctx(secdata, seclen);
97dc49c1f9SCatherine Zhang 		}
98dc49c1f9SCatherine Zhang 	}
99877ce7c1SCatherine Zhang }
100877ce7c1SCatherine Zhang #else
101877ce7c1SCatherine Zhang static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
102877ce7c1SCatherine Zhang { }
103877ce7c1SCatherine Zhang #endif /* CONFIG_SECURITY_NETWORK */
104877ce7c1SCatherine Zhang 
1051da177e4SLinus Torvalds static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
1061da177e4SLinus Torvalds 				struct scm_cookie *scm, int flags)
1071da177e4SLinus Torvalds {
108fd2c3ef7SEric Dumazet 	if (!msg->msg_control) {
1091da177e4SLinus Torvalds 		if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
1101da177e4SLinus Torvalds 			msg->msg_flags |= MSG_CTRUNC;
1111da177e4SLinus Torvalds 		scm_destroy(scm);
1121da177e4SLinus Torvalds 		return;
1131da177e4SLinus Torvalds 	}
1141da177e4SLinus Torvalds 
1151da177e4SLinus Torvalds 	if (test_bit(SOCK_PASSCRED, &sock->flags))
1161da177e4SLinus Torvalds 		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
1171da177e4SLinus Torvalds 
118257b5358SEric W. Biederman 	scm_destroy_cred(scm);
119257b5358SEric W. Biederman 
120877ce7c1SCatherine Zhang 	scm_passec(sock, msg, scm);
121877ce7c1SCatherine Zhang 
1221da177e4SLinus Torvalds 	if (!scm->fp)
1231da177e4SLinus Torvalds 		return;
1241da177e4SLinus Torvalds 
1251da177e4SLinus Torvalds 	scm_detach_fds(msg, scm);
1261da177e4SLinus Torvalds }
1271da177e4SLinus Torvalds 
1281da177e4SLinus Torvalds 
1291da177e4SLinus Torvalds #endif /* __LINUX_NET_SCM_H */
1301da177e4SLinus Torvalds 
131