int put_cmsg_compat(struct msghdr *kmsg, int level, int type, int len, void *data)
{
struct compat_timeval ctv;
+ struct compat_timespec cts;
struct compat_cmsghdr __user *cm = (struct compat_cmsghdr __user *) kmsg->msg_control;
struct compat_cmsghdr cmhdr;
int cmlen;
ctv.tv_sec = tv->tv_sec;
ctv.tv_usec = tv->tv_usec;
data = &ctv;
- len = sizeof(struct compat_timeval);
+ len = sizeof(ctv);
+ }
+ if (level == SOL_SOCKET && type == SO_TIMESTAMPNS) {
+ struct timespec *ts = (struct timespec *)data;
+ cts.tv_sec = ts->tv_sec;
+ cts.tv_nsec = ts->tv_nsec;
+ data = &cts;
+ len = sizeof(cts);
}
cmlen = CMSG_COMPAT_LEN(len);
if (copy_to_user(CMSG_COMPAT_DATA(cm), data, cmlen - sizeof(struct compat_cmsghdr)))
return -EFAULT;
cmlen = CMSG_COMPAT_SPACE(len);
+ if (kmsg->msg_controllen < cmlen)
+ cmlen = kmsg->msg_controllen;
kmsg->msg_control += cmlen;
kmsg->msg_controllen -= cmlen;
return 0;
err = security_file_receive(fp[i]);
if (err)
break;
- err = get_unused_fd();
+ err = get_unused_fd_flags(MSG_CMSG_CLOEXEC & kmsg->msg_flags
+ ? O_CLOEXEC : 0);
if (err < 0)
break;
new_fd = err;