/* Verify that cmsg_len is at least sizeof(struct cmsghdr) */ /* The first check was omitted in <= 2.2.5. The reasoning was that parser checks cmsg_len in any case, so that additional check would be work duplication. But if cmsg_level is not SOL_SOCKET, we do not check for too short ancillary data object at all! Oops. OK, let's add it...
*/ if (!CMSG_OK(msg, cmsg)) goto error;
if (cmsg->cmsg_level != SOL_SOCKET) continue;
switch (cmsg->cmsg_type)
{ case SCM_RIGHTS: if (!ops || ops->family != PF_UNIX) goto error;
err=scm_fp_copy(cmsg, &p->fp); if (err<0) goto error; break; case SCM_CREDENTIALS:
{ struct ucred creds;
kuid_t uid;
kgid_t gid; if (cmsg->cmsg_len != CMSG_LEN(sizeof(struct ucred))) goto error;
memcpy(&creds, CMSG_DATA(cmsg), sizeof(struct ucred));
err = scm_check_creds(&creds); if (err) goto error;
if (!p->pid || pid_vnr(p->pid) != creds.pid) { struct pid *pid;
err = -ESRCH;
pid = find_get_pid(creds.pid); if (!pid) goto error;
/* pass a struct pid reference from * find_get_pid() to scm_replace_pid().
*/
err = scm_replace_pid(p, pid); if (err) {
put_pid(pid); goto error;
}
}
int put_cmsg_notrunc(struct msghdr *msg, int level, int type, int len, void *data)
{ /* Don't produce truncated CMSGs */ if (!msg->msg_control || msg->msg_controllen < CMSG_LEN(len)) return -ETOOSMALL;
/* no use for FD passing from kernel space callers */ if (WARN_ON_ONCE(!msg->msg_control_is_user)) return;
if (msg->msg_flags & MSG_CMSG_COMPAT) {
scm_detach_fds_compat(msg, scm); return;
}
for (i = 0; i < fdmax; i++) {
err = scm_recv_one_fd(scm->fp->fp[i], cmsg_data + i, o_flags); if (err < 0) 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); if (!err)
err = put_user(cmlen, &cm->cmsg_len); if (!err) {
cmlen = CMSG_SPACE(i * sizeof(int)); if (msg->msg_controllen < cmlen)
cmlen = msg->msg_controllen;
msg->msg_control_user += cmlen;
msg->msg_controllen -= cmlen;
}
}
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.
*/
__scm_destroy(scm);
}
EXPORT_SYMBOL(scm_detach_fds);
new_fpl = kmemdup(fpl, offsetof(struct scm_fp_list, fp[fpl->count]),
GFP_KERNEL_ACCOUNT); if (new_fpl) { for (i = 0; i < fpl->count; i++)
get_file(fpl->fp[i]);
/* put_cmsg() doesn't return an error if CMSG is truncated, * that's why we need to opencode these checks here.
*/ if (msg->msg_flags & MSG_CMSG_COMPAT)
len = sizeof(struct compat_cmsghdr) + sizeof(int); else
len = sizeof(struct cmsghdr) + sizeof(int);
if (msg->msg_controllen < len) {
msg->msg_flags |= MSG_CTRUNC; return;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.