#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+
#endif /* _UAPI_ASM_SOCKET_H */
#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+
#endif /* _ASM_SOCKET_H */
#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+
#endif /* _ASM_IA64_SOCKET_H */
#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+
#endif /* _ASM_M32R_SOCKET_H */
#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+
#endif /* _UAPI_ASM_SOCKET_H */
#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+
#endif /* _ASM_SOCKET_H */
#define SCM_TIMESTAMPING_PKTINFO 0x4033
+#define SO_PEERGROUPS 0x4034
+
#endif /* _UAPI_ASM_SOCKET_H */
#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+
#endif /* _ASM_SOCKET_H */
#define SCM_TIMESTAMPING_PKTINFO 0x003c
+#define SO_PEERGROUPS 0x003d
+
/* Security levels - as per NRL IPv6 - don't actually do anything */
#define SO_SECURITY_AUTHENTICATION 0x5001
#define SO_SECURITY_ENCRYPTION_TRANSPORT 0x5002
#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+
#endif /* _XTENSA_SOCKET_H */
#define SCM_TIMESTAMPING_PKTINFO 58
+#define SO_PEERGROUPS 59
+
#endif /* __ASM_GENERIC_SOCKET_H */
}
}
+static int groups_to_user(gid_t __user *dst, const struct group_info *src)
+{
+ struct user_namespace *user_ns = current_user_ns();
+ int i;
+
+ for (i = 0; i < src->ngroups; i++)
+ if (put_user(from_kgid_munged(user_ns, src->gid[i]), dst + i))
+ return -EFAULT;
+
+ return 0;
+}
+
int sock_getsockopt(struct socket *sock, int level, int optname,
char __user *optval, int __user *optlen)
{
goto lenout;
}
+ case SO_PEERGROUPS:
+ {
+ int ret, n;
+
+ if (!sk->sk_peer_cred)
+ return -ENODATA;
+
+ n = sk->sk_peer_cred->group_info->ngroups;
+ if (len < n * sizeof(gid_t)) {
+ len = n * sizeof(gid_t);
+ return put_user(len, optlen) ? -EFAULT : -ERANGE;
+ }
+ len = n * sizeof(gid_t);
+
+ ret = groups_to_user((gid_t __user *)optval,
+ sk->sk_peer_cred->group_info);
+ if (ret)
+ return ret;
+ goto lenout;
+ }
+
case SO_PEERNAME:
{
char address[128];