| .. | .. |
|---|
| 141 | 141 | #define sock_show_fdinfo NULL |
|---|
| 142 | 142 | #endif |
|---|
| 143 | 143 | |
|---|
| 144 | +#ifdef CONFIG_NET_OOB |
|---|
| 145 | + |
|---|
| 146 | +static inline bool sock_oob_capable(struct socket *sock) |
|---|
| 147 | +{ |
|---|
| 148 | + return sock->sk && sock->sk->oob_data; |
|---|
| 149 | +} |
|---|
| 150 | + |
|---|
| 151 | +int __weak sock_oob_attach(struct socket *sock) |
|---|
| 152 | +{ |
|---|
| 153 | + return 0; |
|---|
| 154 | +} |
|---|
| 155 | + |
|---|
| 156 | +void __weak sock_oob_detach(struct socket *sock) |
|---|
| 157 | +{ |
|---|
| 158 | +} |
|---|
| 159 | + |
|---|
| 160 | +int __weak sock_oob_bind(struct socket *sock, struct sockaddr *addr, int len) |
|---|
| 161 | +{ |
|---|
| 162 | + return 0; |
|---|
| 163 | +} |
|---|
| 164 | + |
|---|
| 165 | +long __weak sock_inband_ioctl_redirect(struct socket *sock, |
|---|
| 166 | + unsigned int cmd, unsigned long arg) |
|---|
| 167 | +{ |
|---|
| 168 | + return -ENOTTY; |
|---|
| 169 | +} |
|---|
| 170 | + |
|---|
| 171 | +long __weak sock_oob_ioctl(struct file *file, |
|---|
| 172 | + unsigned int cmd, unsigned long arg) |
|---|
| 173 | +{ |
|---|
| 174 | + return -ENOTTY; |
|---|
| 175 | +} |
|---|
| 176 | + |
|---|
| 177 | +ssize_t __weak sock_oob_write(struct file *filp, |
|---|
| 178 | + const char __user *u_buf, size_t count) |
|---|
| 179 | +{ |
|---|
| 180 | + return -EOPNOTSUPP; |
|---|
| 181 | +} |
|---|
| 182 | + |
|---|
| 183 | +ssize_t __weak sock_oob_read(struct file *filp, |
|---|
| 184 | + char __user *u_buf, size_t count) |
|---|
| 185 | +{ |
|---|
| 186 | + return -EOPNOTSUPP; |
|---|
| 187 | +} |
|---|
| 188 | + |
|---|
| 189 | +__poll_t __weak sock_oob_poll(struct file *filp, |
|---|
| 190 | + struct oob_poll_wait *wait) |
|---|
| 191 | +{ |
|---|
| 192 | + return -EOPNOTSUPP; |
|---|
| 193 | +} |
|---|
| 194 | + |
|---|
| 195 | +#define compat_sock_oob_ioctl compat_ptr_oob_ioctl |
|---|
| 196 | + |
|---|
| 197 | +#else /* !CONFIG_NET_OOB */ |
|---|
| 198 | + |
|---|
| 199 | +static inline bool sock_oob_capable(struct socket *sock) |
|---|
| 200 | +{ |
|---|
| 201 | + return false; |
|---|
| 202 | +} |
|---|
| 203 | + |
|---|
| 204 | +static inline int sock_oob_attach(struct socket *sock) |
|---|
| 205 | +{ |
|---|
| 206 | + return 0; |
|---|
| 207 | +} |
|---|
| 208 | + |
|---|
| 209 | +static inline void sock_oob_detach(struct socket *sock) |
|---|
| 210 | +{ |
|---|
| 211 | +} |
|---|
| 212 | + |
|---|
| 213 | +static int sock_oob_bind(struct socket *sock, |
|---|
| 214 | + struct sockaddr *addr, int len) |
|---|
| 215 | +{ |
|---|
| 216 | + return 0; |
|---|
| 217 | +} |
|---|
| 218 | + |
|---|
| 219 | +static inline long sock_inband_ioctl_redirect(struct socket *sock, |
|---|
| 220 | + unsigned int cmd, unsigned long arg) |
|---|
| 221 | +{ |
|---|
| 222 | + return -ENOTTY; |
|---|
| 223 | +} |
|---|
| 224 | + |
|---|
| 225 | +#define sock_oob_ioctl NULL |
|---|
| 226 | +#define sock_oob_write NULL |
|---|
| 227 | +#define sock_oob_read NULL |
|---|
| 228 | +#define sock_oob_poll NULL |
|---|
| 229 | +#define compat_sock_oob_ioctl NULL |
|---|
| 230 | + |
|---|
| 231 | +#endif /* !CONFIG_NET_OOB */ |
|---|
| 232 | + |
|---|
| 144 | 233 | /* |
|---|
| 145 | 234 | * Socket files have a set of 'special' operations as well as the generic file ones. These don't appear |
|---|
| 146 | 235 | * in the operation structures but are done directly via the socketcall() multiplexor. |
|---|
| .. | .. |
|---|
| 153 | 242 | .write_iter = sock_write_iter, |
|---|
| 154 | 243 | .poll = sock_poll, |
|---|
| 155 | 244 | .unlocked_ioctl = sock_ioctl, |
|---|
| 245 | + .oob_ioctl = sock_oob_ioctl, |
|---|
| 246 | + .oob_write = sock_oob_write, |
|---|
| 247 | + .oob_read = sock_oob_read, |
|---|
| 248 | + .oob_poll = sock_oob_poll, |
|---|
| 156 | 249 | #ifdef CONFIG_COMPAT |
|---|
| 157 | 250 | .compat_ioctl = compat_sock_ioctl, |
|---|
| 251 | + .compat_oob_ioctl = compat_sock_oob_ioctl, |
|---|
| 158 | 252 | #endif |
|---|
| 159 | 253 | .mmap = sock_mmap, |
|---|
| 160 | 254 | .release = sock_close, |
|---|
| .. | .. |
|---|
| 427 | 521 | static int sock_map_fd(struct socket *sock, int flags) |
|---|
| 428 | 522 | { |
|---|
| 429 | 523 | struct file *newfile; |
|---|
| 430 | | - int fd = get_unused_fd_flags(flags); |
|---|
| 524 | + int fd = get_unused_fd_flags(flags), ret; |
|---|
| 431 | 525 | if (unlikely(fd < 0)) { |
|---|
| 432 | 526 | sock_release(sock); |
|---|
| 433 | 527 | return fd; |
|---|
| .. | .. |
|---|
| 435 | 529 | |
|---|
| 436 | 530 | newfile = sock_alloc_file(sock, flags, NULL); |
|---|
| 437 | 531 | if (!IS_ERR(newfile)) { |
|---|
| 532 | + if (IS_ENABLED(CONFIG_NET_OOB) && (flags & SOCK_OOB)) { |
|---|
| 533 | + ret = sock_oob_attach(sock); |
|---|
| 534 | + if (ret < 0) { |
|---|
| 535 | + put_unused_fd(fd); |
|---|
| 536 | + sock_release(sock); |
|---|
| 537 | + return ret; |
|---|
| 538 | + } |
|---|
| 539 | + } |
|---|
| 438 | 540 | fd_install(fd, newfile); |
|---|
| 439 | 541 | return fd; |
|---|
| 440 | 542 | } |
|---|
| .. | .. |
|---|
| 589 | 691 | |
|---|
| 590 | 692 | static void __sock_release(struct socket *sock, struct inode *inode) |
|---|
| 591 | 693 | { |
|---|
| 694 | + if (sock_oob_capable(sock)) |
|---|
| 695 | + sock_oob_detach(sock); |
|---|
| 696 | + |
|---|
| 592 | 697 | if (sock->ops) { |
|---|
| 593 | 698 | struct module *owner = sock->ops->owner; |
|---|
| 594 | 699 | |
|---|
| .. | .. |
|---|
| 1185 | 1290 | false); |
|---|
| 1186 | 1291 | break; |
|---|
| 1187 | 1292 | default: |
|---|
| 1293 | + if (sock_oob_capable(sock)) { |
|---|
| 1294 | + err = sock_inband_ioctl_redirect(sock, cmd, arg); |
|---|
| 1295 | + if (!err || err != -ENOIOCTLCMD) |
|---|
| 1296 | + break; |
|---|
| 1297 | + } |
|---|
| 1188 | 1298 | err = sock_do_ioctl(net, sock, cmd, arg); |
|---|
| 1189 | 1299 | break; |
|---|
| 1190 | 1300 | } |
|---|
| .. | .. |
|---|
| 1498 | 1608 | BUILD_BUG_ON((SOCK_MAX | SOCK_TYPE_MASK) != SOCK_TYPE_MASK); |
|---|
| 1499 | 1609 | BUILD_BUG_ON(SOCK_CLOEXEC & SOCK_TYPE_MASK); |
|---|
| 1500 | 1610 | BUILD_BUG_ON(SOCK_NONBLOCK & SOCK_TYPE_MASK); |
|---|
| 1611 | + BUILD_BUG_ON(SOCK_OOB & SOCK_TYPE_MASK); |
|---|
| 1501 | 1612 | |
|---|
| 1502 | 1613 | flags = type & ~SOCK_TYPE_MASK; |
|---|
| 1503 | | - if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK)) |
|---|
| 1614 | + if (flags & ~(SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_OOB)) |
|---|
| 1504 | 1615 | return -EINVAL; |
|---|
| 1616 | + /* |
|---|
| 1617 | + * Not every protocol family supports out-of-band operations, |
|---|
| 1618 | + * however PF_OOB certainly does: force SOCK_OOB in, so that |
|---|
| 1619 | + * sock_oob_attach() runs for this socket. |
|---|
| 1620 | + */ |
|---|
| 1621 | + if (IS_ENABLED(CONFIG_NET_OOB) && family == AF_OOB) |
|---|
| 1622 | + flags |= SOCK_OOB; |
|---|
| 1505 | 1623 | type &= SOCK_TYPE_MASK; |
|---|
| 1506 | 1624 | |
|---|
| 1507 | 1625 | if (SOCK_NONBLOCK != O_NONBLOCK && (flags & SOCK_NONBLOCK)) |
|---|
| .. | .. |
|---|
| 1511 | 1629 | if (retval < 0) |
|---|
| 1512 | 1630 | return retval; |
|---|
| 1513 | 1631 | |
|---|
| 1514 | | - return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK)); |
|---|
| 1632 | + return sock_map_fd(sock, flags & (O_CLOEXEC | O_NONBLOCK | O_OOB)); |
|---|
| 1515 | 1633 | } |
|---|
| 1516 | 1634 | |
|---|
| 1517 | 1635 | SYSCALL_DEFINE3(socket, int, family, int, type, int, protocol) |
|---|
| .. | .. |
|---|
| 1642 | 1760 | err = security_socket_bind(sock, |
|---|
| 1643 | 1761 | (struct sockaddr *)&address, |
|---|
| 1644 | 1762 | addrlen); |
|---|
| 1763 | + if (sock_oob_capable(sock) && !err) |
|---|
| 1764 | + err = sock_oob_bind(sock, (struct sockaddr *) |
|---|
| 1765 | + &address, addrlen); |
|---|
| 1645 | 1766 | if (!err) |
|---|
| 1646 | 1767 | err = sock->ops->bind(sock, |
|---|
| 1647 | 1768 | (struct sockaddr *) |
|---|