.. | .. |
---|
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 *) |
---|