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