static int do_sysctl_op(int fd, struct sysctl_req *req, int op) { int ret = -1, nr = 1; switch (CTL_TYPE(req->type)) { case __CTL_U32A: nr = CTL_LEN(req->type); /* fallthrough */ case CTL_U32: __SYSCTL_OP(ret, fd, req, u32, nr, op); break; case CTL_32: __SYSCTL_OP(ret, fd, req, s32, nr, op); break; case __CTL_U64A: nr = CTL_LEN(req->type); /* fallthrough */ case CTL_U64: __SYSCTL_OP(ret, fd, req, u64, nr, op); break; case __CTL_STR: nr = CTL_LEN(req->type); __SYSCTL_OP(ret, fd, req, char, nr, op); break; } return ret; }
static int __sysctl_op(int dir, struct sysctl_req *req, int op) { int fd = -1; int ret = -1; int nr = 1; if (dir >= 0) { int flags; if (op == CTL_READ) flags = O_RDONLY; else flags = O_WRONLY; fd = openat(dir, req->name, flags); if (fd < 0) { pr_perror("Can't open sysctl %s", req->name); return -1; } } switch (CTL_TYPE(req->type)) { case __CTL_U32A: nr = CTL_LEN(req->type); case CTL_U32: __SYSCTL_OP(ret, fd, req, u32, nr, op); break; case __CTL_U64A: nr = CTL_LEN(req->type); case CTL_U64: __SYSCTL_OP(ret, fd, req, u64, nr, op); break; case __CTL_STR: nr = CTL_LEN(req->type); __SYSCTL_OP(ret, fd, req, char, nr, op); break; } close_safe(&fd); return ret; }
static int sysctl_userns_arg_size(int type) { switch(CTL_TYPE(type)) { case __CTL_U32A: return sizeof(u32) * CTL_LEN(type); case CTL_U32: return sizeof(u32); case CTL_32: return sizeof(s32); case __CTL_U64A: return sizeof(u64) * CTL_LEN(type); case CTL_U64: return sizeof(u64); case __CTL_STR: return sizeof(char) * CTL_LEN(type) + 1; default: pr_err("unknown arg type %d\n", type); /* Ensure overflow to cause an error */ return MAX_UNSFD_MSG_SIZE; } }