Kopałem teraz nieco i mam takie oto dziwne rzeczy. Z
net/core/sock.c:
Kod: Zaznacz cały
int sock_setsockopt(struct socket *sock, int level, int optname,
442 char __user *optval, int optlen)
443 {
444 struct sock *sk=sock->sk;
445 int val;
446 int valbool;
447 struct linger ling;
448 int ret = 0;
449
450 /*
451 * Options without arguments
452 */
453
454 if (optname == SO_BINDTODEVICE)
455 return sock_bindtodevice(sk, optval, optlen);
456 */dziwne, że w ogóle tego nie ma w switch tylko tak sobie luzem sprawdza*/
457 if (optlen < sizeof(int))
458 return -EINVAL;
459
460 if (get_user(val, (int __user *)optval))
461 return -EFAULT;
462
463 valbool = val?1:0;
464
465 lock_sock(sk);
466
467 switch(optname) {
468 case SO_DEBUG:
469 if (val && !capable(CAP_NET_ADMIN)) {
470 ret = -EACCES;
471 } else
472 sock_valbool_flag(sk, SOCK_DBG, valbool);
473 break;
474 case SO_REUSEADDR:
475 sk->sk_reuse = valbool;
476 break;
477 case SO_TYPE:
478 case SO_ERROR:
479 ret = -ENOPROTOOPT;
480 break;
481 case SO_DONTROUTE:
482 sock_valbool_flag(sk, SOCK_LOCALROUTE, valbool);
483 break;
484 case SO_BROADCAST:
485 sock_valbool_flag(sk, SOCK_BROADCAST, valbool);
486 break;
487 case SO_SNDBUF:
488 /* Don't error on this BSD doesn't and if you think
489 about it this is right. Otherwise apps have to
490 play 'guess the biggest size' games. RCVBUF/SNDBUF
491 are treated in BSD as hints */
492
493 if (val > sysctl_wmem_max)
494 val = sysctl_wmem_max;
495 set_sndbuf:
496 sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
497 if ((val * 2) < SOCK_MIN_SNDBUF)
498 sk->sk_sndbuf = SOCK_MIN_SNDBUF;
499 else
500 sk->sk_sndbuf = val * 2;
501
502 /*
503 * Wake up sending tasks if we
504 * upped the value.
505 */
506 sk->sk_write_space(sk);
507 break;
508
509 case SO_SNDBUFFORCE:
510 if (!capable(CAP_NET_ADMIN)) {
511 ret = -EPERM;
512 break;
513 }
514 goto set_sndbuf;
515
516 case SO_RCVBUF:
517 /* Don't error on this BSD doesn't and if you think
518 about it this is right. Otherwise apps have to
519 play 'guess the biggest size' games. RCVBUF/SNDBUF
520 are treated in BSD as hints */
521
522 if (val > sysctl_rmem_max)
523 val = sysctl_rmem_max;
524 set_rcvbuf:
525 sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
526 /*
527 * We double it on the way in to account for
528 * "struct sk_buff" etc. overhead. Applications
529 * assume that the SO_RCVBUF setting they make will
530 * allow that much actual data to be received on that
531 * socket.
532 *
533 * Applications are unaware that "struct sk_buff" and
534 * other overheads allocate from the receive buffer
535 * during socket buffer allocation.
536 *
537 * And after considering the possible alternatives,
538 * returning the value we actually used in getsockopt
539 * is the most desirable behavior.
540 */
541 if ((val * 2) < SOCK_MIN_RCVBUF)
542 sk->sk_rcvbuf = SOCK_MIN_RCVBUF;
543 else
544 sk->sk_rcvbuf = val * 2;
545 break;
546
547 case SO_RCVBUFFORCE:
548 if (!capable(CAP_NET_ADMIN)) {
549 ret = -EPERM;
550 break;
551 }
552 goto set_rcvbuf;
553
554 case SO_KEEPALIVE:
555 #ifdef CONFIG_INET
556 if (sk->sk_protocol == IPPROTO_TCP)
557 tcp_set_keepalive(sk, valbool);
558 #endif
559 sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
560 break;
561
562 case SO_OOBINLINE:
563 sock_valbool_flag(sk, SOCK_URGINLINE, valbool);
564 break;
565
566 case SO_NO_CHECK:
567 sk->sk_no_check = valbool;
568 break;
569
570 case SO_PRIORITY:
571 if ((val >= 0 && val <= 6) || capable(CAP_NET_ADMIN))
572 sk->sk_priority = val;
573 else
574 ret = -EPERM;
575 break;
576
577 case SO_LINGER:
578 if (optlen < sizeof(ling)) {
579 ret = -EINVAL; /* 1003.1g */
580 break;
581 }
582 if (copy_from_user(&ling,optval,sizeof(ling))) {
583 ret = -EFAULT;
584 break;
585 }
586 if (!ling.l_onoff)
587 sock_reset_flag(sk, SOCK_LINGER);
588 else {
589 #if (BITS_PER_LONG == 32)
590 if ((unsigned int)ling.l_linger >= MAX_SCHEDULE_TIMEOUT/HZ)
591 sk->sk_lingertime = MAX_SCHEDULE_TIMEOUT;
592 else
593 #endif
594 sk->sk_lingertime = (unsigned int)ling.l_linger * HZ;
595 sock_set_flag(sk, SOCK_LINGER);
596 }
597 break;
598
599 case SO_BSDCOMPAT:
600 sock_warn_obsolete_bsdism("setsockopt");
601 break;
602
603 case SO_PASSCRED:
604 if (valbool)
605 set_bit(SOCK_PASSCRED, &sock->flags);
606 else
607 clear_bit(SOCK_PASSCRED, &sock->flags);
608 break;
609
610 case SO_TIMESTAMP:
611 case SO_TIMESTAMPNS:
612 if (valbool) {
613 if (optname == SO_TIMESTAMP)
614 sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
615 else
616 sock_set_flag(sk, SOCK_RCVTSTAMPNS);
617 sock_set_flag(sk, SOCK_RCVTSTAMP);
618 sock_enable_timestamp(sk);
619 } else {
620 sock_reset_flag(sk, SOCK_RCVTSTAMP);
621 sock_reset_flag(sk, SOCK_RCVTSTAMPNS);
622 }
623 break;
624
625 case SO_RCVLOWAT:
626 if (val < 0)
627 val = INT_MAX;
628 sk->sk_rcvlowat = val ? : 1;
629 break;
630
631 case SO_RCVTIMEO:
632 ret = sock_set_timeout(&sk->sk_rcvtimeo, optval, optlen);
633 break;
634
635 case SO_SNDTIMEO:
636 ret = sock_set_timeout(&sk->sk_sndtimeo, optval, optlen);
637 break;
638
639 case SO_ATTACH_FILTER:
640 ret = -EINVAL;
641 if (optlen == sizeof(struct sock_fprog)) {
642 struct sock_fprog fprog;
643
644 ret = -EFAULT;
645 if (copy_from_user(&fprog, optval, sizeof(fprog)))
646 break;
647
648 ret = sk_attach_filter(&fprog, sk);
649 }
650 break;
651
652 case SO_DETACH_FILTER:
653 ret = sk_detach_filter(sk);
654 break;
655
656 case SO_PASSSEC:
657 if (valbool)
658 set_bit(SOCK_PASSSEC, &sock->flags);
659 else
660 clear_bit(SOCK_PASSSEC, &sock->flags);
661 break;
662 case SO_MARK:
663 if (!capable(CAP_NET_ADMIN))
664 ret = -EPERM;
665 else {
666 sk->sk_mark = val;
667 }
668 break;
669
670 /* We implement the SO_SNDLOWAT etc to
671 not be settable (1003.1g 5.3) */
672 default:
673 ret = -ENOPROTOOPT;
674 break;
675 }
676 release_sock(sk);
677 return ret;
678 }
Jak widać w instrukcji:
nie sprawdza zupełnie nic co może mieć coś wspólnego z prawami czy bezpieczeństem, od razu wywołuje
sock_bindtodevice() z pliku "net/core/sock.c" . A tutaj zaś jest sprawdzenie:
Kod: Zaznacz cały
ret = -EPERM;
if (!capable(CAP_NET_RAW))
goto out;
Czyli jeśli CAP_NET_RAW jest niespełniony, a nie CAP_NET_ADMIN (jak było napisane tamtej grupie dyskusyjnej) to funkcja kończy swoje działanie z kodem błędu -EPERM, czyli właśnie Twoje:
Kod: Zaznacz cały
#define EPERM 1 /* Operation not permitted */
No to mamy źródło sprawcy. Wiesz zawsze możesz usunąć ten warunek sprawdzania z kodu jądra i przekompilować jajko na nowo
Mam nadzieję, że w jakikolwiek sposób pomogłem.