xref: /openbmc/linux/include/net/scm.h (revision dc49c1f94e3469d94b952e8f5160dd4ccd791d79)
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>
6*dc49c1f9SCatherine Zhang #include <linux/security.h>
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds /* Well, we should have at least one descriptor open
91da177e4SLinus Torvalds  * to accept passed FDs 8)
101da177e4SLinus Torvalds  */
111da177e4SLinus Torvalds #define SCM_MAX_FD	(OPEN_MAX-1)
121da177e4SLinus Torvalds 
131da177e4SLinus Torvalds struct scm_fp_list
141da177e4SLinus Torvalds {
151da177e4SLinus Torvalds 	int		count;
161da177e4SLinus Torvalds 	struct file	*fp[SCM_MAX_FD];
171da177e4SLinus Torvalds };
181da177e4SLinus Torvalds 
191da177e4SLinus Torvalds struct scm_cookie
201da177e4SLinus Torvalds {
211da177e4SLinus Torvalds 	struct ucred		creds;		/* Skb credentials	*/
221da177e4SLinus Torvalds 	struct scm_fp_list	*fp;		/* Passed files		*/
23877ce7c1SCatherine Zhang #ifdef CONFIG_SECURITY_NETWORK
24*dc49c1f9SCatherine Zhang 	u32			secid;		/* Passed security ID 	*/
25877ce7c1SCatherine Zhang #endif
261da177e4SLinus Torvalds 	unsigned long		seq;		/* Connection seqno	*/
271da177e4SLinus Torvalds };
281da177e4SLinus Torvalds 
291da177e4SLinus Torvalds extern void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm);
301da177e4SLinus Torvalds extern void scm_detach_fds_compat(struct msghdr *msg, struct scm_cookie *scm);
311da177e4SLinus Torvalds extern int __scm_send(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm);
321da177e4SLinus Torvalds extern void __scm_destroy(struct scm_cookie *scm);
331da177e4SLinus Torvalds extern struct scm_fp_list * scm_fp_dup(struct scm_fp_list *fpl);
341da177e4SLinus Torvalds 
35*dc49c1f9SCatherine Zhang #ifdef CONFIG_SECURITY_NETWORK
36*dc49c1f9SCatherine Zhang static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
37*dc49c1f9SCatherine Zhang {
38*dc49c1f9SCatherine Zhang 	security_socket_getpeersec_dgram(sock, NULL, &scm->secid);
39*dc49c1f9SCatherine Zhang }
40*dc49c1f9SCatherine Zhang #else
41*dc49c1f9SCatherine Zhang static __inline__ void unix_get_peersec_dgram(struct socket *sock, struct scm_cookie *scm)
42*dc49c1f9SCatherine Zhang { }
43*dc49c1f9SCatherine Zhang #endif /* CONFIG_SECURITY_NETWORK */
44*dc49c1f9SCatherine Zhang 
451da177e4SLinus Torvalds static __inline__ void scm_destroy(struct scm_cookie *scm)
461da177e4SLinus Torvalds {
471da177e4SLinus Torvalds 	if (scm && scm->fp)
481da177e4SLinus Torvalds 		__scm_destroy(scm);
491da177e4SLinus Torvalds }
501da177e4SLinus Torvalds 
511da177e4SLinus Torvalds static __inline__ int scm_send(struct socket *sock, struct msghdr *msg,
521da177e4SLinus Torvalds 			       struct scm_cookie *scm)
531da177e4SLinus Torvalds {
541d541dddSBenjamin LaHaise 	struct task_struct *p = current;
551d541dddSBenjamin LaHaise 	scm->creds.uid = p->uid;
561d541dddSBenjamin LaHaise 	scm->creds.gid = p->gid;
571d541dddSBenjamin LaHaise 	scm->creds.pid = p->tgid;
581d541dddSBenjamin LaHaise 	scm->fp = NULL;
591d541dddSBenjamin LaHaise 	scm->seq = 0;
60*dc49c1f9SCatherine Zhang 	unix_get_peersec_dgram(sock, scm);
611da177e4SLinus Torvalds 	if (msg->msg_controllen <= 0)
621da177e4SLinus Torvalds 		return 0;
631da177e4SLinus Torvalds 	return __scm_send(sock, msg, scm);
641da177e4SLinus Torvalds }
651da177e4SLinus Torvalds 
66877ce7c1SCatherine Zhang #ifdef CONFIG_SECURITY_NETWORK
67877ce7c1SCatherine Zhang static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
68877ce7c1SCatherine Zhang {
69*dc49c1f9SCatherine Zhang 	char *secdata;
70*dc49c1f9SCatherine Zhang 	u32 seclen;
71*dc49c1f9SCatherine Zhang 	int err;
72*dc49c1f9SCatherine Zhang 
73*dc49c1f9SCatherine Zhang 	if (test_bit(SOCK_PASSSEC, &sock->flags)) {
74*dc49c1f9SCatherine Zhang 		err = security_secid_to_secctx(scm->secid, &secdata, &seclen);
75*dc49c1f9SCatherine Zhang 
76*dc49c1f9SCatherine Zhang 		if (!err) {
77*dc49c1f9SCatherine Zhang 			put_cmsg(msg, SOL_SOCKET, SCM_SECURITY, seclen, secdata);
78*dc49c1f9SCatherine Zhang 			security_release_secctx(secdata, seclen);
79*dc49c1f9SCatherine Zhang 		}
80*dc49c1f9SCatherine Zhang 	}
81877ce7c1SCatherine Zhang }
82877ce7c1SCatherine Zhang #else
83877ce7c1SCatherine Zhang static inline void scm_passec(struct socket *sock, struct msghdr *msg, struct scm_cookie *scm)
84877ce7c1SCatherine Zhang { }
85877ce7c1SCatherine Zhang #endif /* CONFIG_SECURITY_NETWORK */
86877ce7c1SCatherine Zhang 
871da177e4SLinus Torvalds static __inline__ void scm_recv(struct socket *sock, struct msghdr *msg,
881da177e4SLinus Torvalds 				struct scm_cookie *scm, int flags)
891da177e4SLinus Torvalds {
901da177e4SLinus Torvalds 	if (!msg->msg_control)
911da177e4SLinus Torvalds 	{
921da177e4SLinus Torvalds 		if (test_bit(SOCK_PASSCRED, &sock->flags) || scm->fp)
931da177e4SLinus Torvalds 			msg->msg_flags |= MSG_CTRUNC;
941da177e4SLinus Torvalds 		scm_destroy(scm);
951da177e4SLinus Torvalds 		return;
961da177e4SLinus Torvalds 	}
971da177e4SLinus Torvalds 
981da177e4SLinus Torvalds 	if (test_bit(SOCK_PASSCRED, &sock->flags))
991da177e4SLinus Torvalds 		put_cmsg(msg, SOL_SOCKET, SCM_CREDENTIALS, sizeof(scm->creds), &scm->creds);
1001da177e4SLinus Torvalds 
101877ce7c1SCatherine Zhang 	scm_passec(sock, msg, scm);
102877ce7c1SCatherine Zhang 
1031da177e4SLinus Torvalds 	if (!scm->fp)
1041da177e4SLinus Torvalds 		return;
1051da177e4SLinus Torvalds 
1061da177e4SLinus Torvalds 	scm_detach_fds(msg, scm);
1071da177e4SLinus Torvalds }
1081da177e4SLinus Torvalds 
1091da177e4SLinus Torvalds 
1101da177e4SLinus Torvalds #endif /* __LINUX_NET_SCM_H */
1111da177e4SLinus Torvalds 
112