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