Loading net/core/scm.c +51 −43 Original line number Diff line number Diff line Loading @@ -277,59 +277,66 @@ void put_cmsg_scm_timestamping(struct msghdr *msg, struct scm_timestamping_inter } EXPORT_SYMBOL(put_cmsg_scm_timestamping); void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) static int __scm_install_fd(struct file *file, int __user *ufd, int o_flags) { struct cmsghdr __user *cm = (__force struct cmsghdr __user*)msg->msg_control; int fdmax = 0; int fdnum = scm->fp->count; struct file **fp = scm->fp->fp; int __user *cmfptr; int err = 0, i; if (MSG_CMSG_COMPAT & msg->msg_flags) { scm_detach_fds_compat(msg, scm); return; } struct socket *sock; int new_fd; int error; if (msg->msg_controllen > sizeof(struct cmsghdr)) fdmax = ((msg->msg_controllen - sizeof(struct cmsghdr)) / sizeof(int)); error = security_file_receive(file); if (error) return error; if (fdnum < fdmax) fdmax = fdnum; new_fd = get_unused_fd_flags(o_flags); if (new_fd < 0) return new_fd; for (i=0, cmfptr =(int __user *)CMSG_USER_DATA(cm); i<fdmax; i++, cmfptr++) { struct socket *sock; int new_fd; err = security_file_receive(fp[i]); if (err) break; err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & msg->msg_flags ? O_CLOEXEC : 0); if (err < 0) break; new_fd = err; err = put_user(new_fd, cmfptr); if (err) { error = put_user(new_fd, ufd); if (error) { put_unused_fd(new_fd); break; return error; } /* Bump the usage count and install the file. */ sock = sock_from_file(fp[i], &err); sock = sock_from_file(file, &error); if (sock) { sock_update_netprioidx(&sock->sk->sk_cgrp_data); sock_update_classid(&sock->sk->sk_cgrp_data); } fd_install(new_fd, get_file(fp[i])); fd_install(new_fd, get_file(file)); return error; } if (i > 0) static int scm_max_fds(struct msghdr *msg) { if (msg->msg_controllen <= sizeof(struct cmsghdr)) return 0; return (msg->msg_controllen - sizeof(struct cmsghdr)) / sizeof(int); } void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) { struct cmsghdr __user *cm = (__force struct cmsghdr __user*)msg->msg_control; int o_flags = (msg->msg_flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0; int fdmax = min_t(int, scm_max_fds(msg), scm->fp->count); int __user *cmsg_data = CMSG_USER_DATA(cm); int err = 0, i; if (msg->msg_flags & MSG_CMSG_COMPAT) { scm_detach_fds_compat(msg, scm); return; } for (i = 0; i < fdmax; i++) { err = __scm_install_fd(scm->fp->fp[i], cmsg_data + i, o_flags); if (err) break; } if (i > 0) { int cmlen = CMSG_LEN(i * sizeof(int)); err = put_user(SOL_SOCKET, &cm->cmsg_level); if (!err) err = put_user(SCM_RIGHTS, &cm->cmsg_type); Loading @@ -343,12 +350,13 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) msg->msg_controllen -= cmlen; } } if (i < fdnum || (fdnum && fdmax <= 0)) if (i < scm->fp->count || (scm->fp->count && fdmax <= 0)) msg->msg_flags |= MSG_CTRUNC; /* * All of the files that fit in the message have had their * usage counts incremented, so we just free the list. * All of the files that fit in the message have had their usage counts * incremented, so we just free the list. */ __scm_destroy(scm); } Loading Loading
net/core/scm.c +51 −43 Original line number Diff line number Diff line Loading @@ -277,59 +277,66 @@ void put_cmsg_scm_timestamping(struct msghdr *msg, struct scm_timestamping_inter } EXPORT_SYMBOL(put_cmsg_scm_timestamping); void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) static int __scm_install_fd(struct file *file, int __user *ufd, int o_flags) { struct cmsghdr __user *cm = (__force struct cmsghdr __user*)msg->msg_control; int fdmax = 0; int fdnum = scm->fp->count; struct file **fp = scm->fp->fp; int __user *cmfptr; int err = 0, i; if (MSG_CMSG_COMPAT & msg->msg_flags) { scm_detach_fds_compat(msg, scm); return; } struct socket *sock; int new_fd; int error; if (msg->msg_controllen > sizeof(struct cmsghdr)) fdmax = ((msg->msg_controllen - sizeof(struct cmsghdr)) / sizeof(int)); error = security_file_receive(file); if (error) return error; if (fdnum < fdmax) fdmax = fdnum; new_fd = get_unused_fd_flags(o_flags); if (new_fd < 0) return new_fd; for (i=0, cmfptr =(int __user *)CMSG_USER_DATA(cm); i<fdmax; i++, cmfptr++) { struct socket *sock; int new_fd; err = security_file_receive(fp[i]); if (err) break; err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & msg->msg_flags ? O_CLOEXEC : 0); if (err < 0) break; new_fd = err; err = put_user(new_fd, cmfptr); if (err) { error = put_user(new_fd, ufd); if (error) { put_unused_fd(new_fd); break; return error; } /* Bump the usage count and install the file. */ sock = sock_from_file(fp[i], &err); sock = sock_from_file(file, &error); if (sock) { sock_update_netprioidx(&sock->sk->sk_cgrp_data); sock_update_classid(&sock->sk->sk_cgrp_data); } fd_install(new_fd, get_file(fp[i])); fd_install(new_fd, get_file(file)); return error; } if (i > 0) static int scm_max_fds(struct msghdr *msg) { if (msg->msg_controllen <= sizeof(struct cmsghdr)) return 0; return (msg->msg_controllen - sizeof(struct cmsghdr)) / sizeof(int); } void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) { struct cmsghdr __user *cm = (__force struct cmsghdr __user*)msg->msg_control; int o_flags = (msg->msg_flags & MSG_CMSG_CLOEXEC) ? O_CLOEXEC : 0; int fdmax = min_t(int, scm_max_fds(msg), scm->fp->count); int __user *cmsg_data = CMSG_USER_DATA(cm); int err = 0, i; if (msg->msg_flags & MSG_CMSG_COMPAT) { scm_detach_fds_compat(msg, scm); return; } for (i = 0; i < fdmax; i++) { err = __scm_install_fd(scm->fp->fp[i], cmsg_data + i, o_flags); if (err) break; } if (i > 0) { int cmlen = CMSG_LEN(i * sizeof(int)); err = put_user(SOL_SOCKET, &cm->cmsg_level); if (!err) err = put_user(SCM_RIGHTS, &cm->cmsg_type); Loading @@ -343,12 +350,13 @@ void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm) msg->msg_controllen -= cmlen; } } if (i < fdnum || (fdnum && fdmax <= 0)) if (i < scm->fp->count || (scm->fp->count && fdmax <= 0)) msg->msg_flags |= MSG_CTRUNC; /* * All of the files that fit in the message have had their * usage counts incremented, so we just free the list. * All of the files that fit in the message have had their usage counts * incremented, so we just free the list. */ __scm_destroy(scm); } Loading