xref: /openbmc/linux/include/net/scm.h (revision b488893a390edfe027bae7a46e9af8083e740668)
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>
7*b488893aSPavel Emelyanov #include <linux/pid.h>
8*b488893aSPavel 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 
151da177e4SLinus Torvalds struct scm_fp_list
161da177e4SLinus Torvalds {
171da177e4SLinus Torvalds 	int		count;
181da177e4SLinus Torvalds 	struct file	*fp[SCM_MAX_FD];
191da177e4SLinus Torvalds };
201da177e4SLinus Torvalds 
211da177e4SLinus Torvalds struct scm_cookie
221da177e4SLinus Torvalds {
231da177e4SLinus Torvalds 	struct ucred		creds;		/* Skb credentials	*/
241da177e4SLinus Torvalds 	struct scm_fp_list	*fp;		/* Passed files		*/
25877ce7c1SCatherine Zhang #ifdef CONFIG_SECURITY_NETWORK
26dc49c1f9SCatherine Zhang 	u32			secid;		/* Passed security ID 	*/
27877ce7c1SCatherine Zhang #endif
281da177e4SLinus Torvalds 	unsigned long		seq;		/* Connection seqno	*/
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 
471da177e4SLinus Torvalds static __inline__ void scm_destroy(struct scm_cookie *scm)
481da177e4SLinus Torvalds {
491da177e4SLinus Torvalds 	if (scm && scm->fp)
501da177e4SLinus Torvalds 		__scm_destroy(scm);
511da177e4SLinus Torvalds }
521da177e4SLinus Torvalds 
531da177e4SLinus Torvalds static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
541da177e4SLinus Torvalds 			       struct scm_cookie *scm)
551da177e4SLinus Torvalds {
561d541dddSBenjamin LaHaise 	struct task_struct *p = current;
571d541dddSBenjamin LaHaise 	scm->creds.uid = p->uid;
581d541dddSBenjamin LaHaise 	scm->creds.gid = p->gid;
59*b488893aSPavel Emelyanov 	scm->creds.pid = task_tgid_vnr(p);
601d541dddSBenjamin LaHaise 	scm->fp = NULL;
611d541dddSBenjamin LaHaise 	scm->seq = 0;
62dc49c1f9SCatherine Zhang 	unix_get_peersec_dgram(sock, scm);
631da177e4SLinus Torvalds 	if (msg->msg_controllen <= 0)
641da177e4SLinus Torvalds 		return 0;
651da177e4SLinus Torvalds 	return __scm_send(sock, msg, scm);
661da177e4SLinus Torvalds }
671da177e4SLinus Torvalds 
68877ce7c1SCatherine Zhang #ifdef CONFIG_SECURITY_NETWORK
69877ce7c1SCatherine Zhang static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
70877ce7c1SCatherine Zhang {
71dc49c1f9SCatherine Zhang 	char *secdata;
72dc49c1f9SCatherine Zhang 	u32 seclen;
73dc49c1f9SCatherine Zhang 	int err;
74dc49c1f9SCatherine Zhang 
75dc49c1f9SCatherine Zhang 	if (test_bit(SOCK_PASSSEC, &sock->flags)) {
76dc49c1f9SCatherine Zhang 		err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
77dc49c1f9SCatherine Zhang 
78dc49c1f9SCatherine Zhang 		if (!err) {
79dc49c1f9SCatherine Zhang 			put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
80dc49c1f9SCatherine Zhang 			security_release_secctx(secdata, seclen);
81dc49c1f9SCatherine Zhang 		}
82dc49c1f9SCatherine Zhang 	}
83877ce7c1SCatherine Zhang }
84877ce7c1SCatherine Zhang #else
85877ce7c1SCatherine Zhang static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
86877ce7c1SCatherine Zhang { }
87877ce7c1SCatherine Zhang #endif /* CONFIG_SECURITY_NETWORK */
88877ce7c1SCatherine Zhang 
891da177e4SLinus Torvalds static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
901da177e4SLinus Torvalds 				struct scm_cookie *scm, int flags)
911da177e4SLinus Torvalds {
921da177e4SLinus Torvalds 	if (!msg->msg_control)
931da177e4SLinus Torvalds 	{
941da177e4SLinus Torvalds 		if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
951da177e4SLinus Torvalds 			msg->msg_flags |= MSG_CTRUNC;
961da177e4SLinus Torvalds 		scm_destroy(scm);
971da177e4SLinus Torvalds 		return;
981da177e4SLinus Torvalds 	}
991da177e4SLinus Torvalds 
1001da177e4SLinus Torvalds 	if (test_bit(SOCK_PASSCRED, &sock->flags))
1011da177e4SLinus Torvalds 		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
1021da177e4SLinus Torvalds 
103877ce7c1SCatherine Zhang 	scm_passec(sock, msg, scm);
104877ce7c1SCatherine Zhang 
1051da177e4SLinus Torvalds 	if (!scm->fp)
1061da177e4SLinus Torvalds 		return;
1071da177e4SLinus Torvalds 
1081da177e4SLinus Torvalds 	scm_detach_fds(msg, scm);
1091da177e4SLinus Torvalds }
1101da177e4SLinus Torvalds 
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds #endif /* __LINUX_NET_SCM_H */
1131da177e4SLinus Torvalds 
114