Re: [PATCH testsuite] tests/sctp: fix setting of the SCTP_EVENTS sockopt

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Feb 24, 2020 at 4:24 PM Richard Haines
<richard_c_haines@xxxxxxxxxxxxxx> wrote:
> On Mon, 2020-02-24 at 13:47 +0100, Ondrej Mosnacek wrote:
> > First, the setting of SCTP_EVENTS socket option in sctp_server.c is
> > completely wrong -- it assumes little-endian byte order and uses a
> > plain
> > int instead of the dedicated sctp_event_subscribe struct.
> >
> > Second, the usage in sctp_peeloff_server.c is correct, but it may
> > lead
> > to errors when the SCTP header definitions are newer than what the
> > kernel supports. In such case the size of struct sctp_event_subscribe
> > may be higher than the kernel's version and the setsockopt(2) may
> > fail
> > with -EINVAL due to the 'optlen > sizeof(struct
> > sctp_event_subscribe)'
> > check in net/sctp/socket.c:sctp_setsockopt_events().
> >
> > To fix this, introduce a common function that does what the
> > sctp_peeloff_server's set_subscr_events() did, but also truncates the
> > optlen to only those fields that we use.
>
> Thanks for fixing these problems. How did the problems come to light,
> just via the header file changes or some tests failing on a certain
> kernel ?

Apparently, struct sctp_event_subscribe has been extended by a new
field between kernel 5.4 and 5.5 [1] and this caused the error to
appear in CKI testing [2] when Fedora 31 moved to kernel 5.5 (it
installed the tested 5.4 stable rc kernel and booted into it, while
the kernel-headers package stayed at the distro's 5.5 version). The
endianness issue never seemed to have triggered actual failures when
we ran the tests internally on big-endian s390x systems. (I'm
wondering if the SCTP_EVENTS setsockopt() is even needed there...?)

[1] https://github.com/torvalds/linux/blame/master/include/uapi/linux/sctp.h#L623
[2] https://lore.kernel.org/stable/CAFqZXNvnywGVwqJhXcfwpmx2mmu8ajAUOdy0Ny8PvsT=Rg_3Qg@xxxxxxxxxxxxxx/T/

>
> >
> > Fixes: c38b57ffdac4 ("selinux-testsuite: Add SCTP test support")
> > Signed-off-by: Ondrej Mosnacek <omosnace@xxxxxxxxxx>
> > ---
> >  tests/sctp/sctp_common.c         | 20 ++++++++++++++++++++
> >  tests/sctp/sctp_common.h         |  1 +
> >  tests/sctp/sctp_peeloff_server.c | 28 ++++++++--------------------
> >  tests/sctp/sctp_server.c         |  2 +-
> >  4 files changed, 30 insertions(+), 21 deletions(-)
> >
> > diff --git a/tests/sctp/sctp_common.c b/tests/sctp/sctp_common.c
> > index 100ab22..089af2a 100644
> > --- a/tests/sctp/sctp_common.c
> > +++ b/tests/sctp/sctp_common.c
> > @@ -1,5 +1,8 @@
> >  #include "sctp_common.h"
> >
> > +#define member_size(type, member) sizeof(((type *)0)->member)
> > +#define sizeof_up_to(type, member) (offsetof(type, member) +
> > member_size(type, member))
> > +
> >  void print_context(int fd, char *text)
> >  {
> >       char *context;
> > @@ -99,3 +102,20 @@ void print_ip_option(int fd, bool ipv4, char
> > *text)
> >               printf("%s No IP Options set\n", text);
> >       }
> >  }
> > +
> > +int set_subscr_events(int fd, int data_io, int association)
> > +{
> > +     struct sctp_event_subscribe subscr_events;
> > +
> > +     memset(&subscr_events, 0, sizeof(subscr_events));
> > +     subscr_events.sctp_data_io_event = data_io;
> > +     subscr_events.sctp_association_event = association;
> > +
> > +     /*
> > +      * Truncate optlen to just the fields we touch to avoid errors
> > when
> > +      * the uapi headers are newer than the running kernel.
> > +      */
> > +     return setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS,
> > &subscr_events,
> > +                       sizeof_up_to(struct sctp_event_subscribe,
> > +                                    sctp_association_event));
> > +}
> > diff --git a/tests/sctp/sctp_common.h b/tests/sctp/sctp_common.h
> > index d5c1397..351ee37 100644
> > --- a/tests/sctp/sctp_common.h
> > +++ b/tests/sctp/sctp_common.h
> > @@ -25,3 +25,4 @@ void print_context(int fd, char *text);
> >  void print_addr_info(struct sockaddr *sin, char *text);
> >  char *get_ip_option(int fd, bool ipv4, socklen_t *opt_len);
> >  void print_ip_option(int fd, bool ipv4, char *text);
> > +int set_subscr_events(int fd, int data_io, int association);
> > diff --git a/tests/sctp/sctp_peeloff_server.c
> > b/tests/sctp/sctp_peeloff_server.c
> > index 4a5110a..093c6c0 100644
> > --- a/tests/sctp/sctp_peeloff_server.c
> > +++ b/tests/sctp/sctp_peeloff_server.c
> > @@ -16,24 +16,6 @@ static void usage(char *progname)
> >       exit(1);
> >  }
> >
> > -static void set_subscr_events(int fd, int value)
> > -{
> > -     int result;
> > -     struct sctp_event_subscribe subscr_events;
> > -
> > -     memset(&subscr_events, 0, sizeof(subscr_events));
> > -     subscr_events.sctp_association_event = value;
> > -     /* subscr_events.sctp_data_io_event = value; */
> > -
> > -     result = setsockopt(fd, IPPROTO_SCTP, SCTP_EVENTS,
> > -                         &subscr_events, sizeof(subscr_events));
> > -     if (result < 0) {
> > -             perror("Server setsockopt: SCTP_EVENTS");
> > -             close(fd);
> > -             exit(1);
> > -     }
> > -}
> > -
> >  static sctp_assoc_t handle_event(void *buf)
> >  {
> >       union sctp_notification *snp = buf;
> > @@ -166,7 +148,13 @@ int main(int argc, char **argv)
> >       }
> >
> >       do {
> > -             set_subscr_events(sock, 1); /* Get assoc_id for
> > sctp_peeloff() */
> > +             /* Get assoc_id for sctp_peeloff() */
> > +             result = set_subscr_events(sock, 0, 1);
> > +             if (result < 0) {
> > +                     perror("Server setsockopt: SCTP_EVENTS");
> > +                     close(sock);
> > +                     exit(1);
> > +             }
> >               sinlen = sizeof(sin);
> >               flags = 0;
> >
> > @@ -192,7 +180,7 @@ int main(int argc, char **argv)
> >                               exit(1);
> >                       }
> >                       /* No more notifications */
> > -                     set_subscr_events(sock, 0);
> > +                     set_subscr_events(sock, 0, 0);
> >
> >                       peeloff_sk = sctp_peeloff(sock, assoc_id);
> >                       if (peeloff_sk < 0) {
> > diff --git a/tests/sctp/sctp_server.c b/tests/sctp/sctp_server.c
> > index 4659ed1..7f2cd20 100644
> > --- a/tests/sctp/sctp_server.c
> > +++ b/tests/sctp/sctp_server.c
> > @@ -134,7 +134,7 @@ int main(int argc, char **argv)
> >       }
> >
> >       /* Enables sctp_data_io_events for sctp_recvmsg(3) for
> > assoc_id. */
> > -     result = setsockopt(sock, SOL_SCTP, SCTP_EVENTS, &on,
> > sizeof(on));
> > +     result = set_subscr_events(sock, on, 0);
> >       if (result < 0) {
> >               perror("Server setsockopt: SCTP_EVENTS");
> >               close(sock);
>


-- 
Ondrej Mosnacek <omosnace at redhat dot com>
Software Engineer, Security Technologies
Red Hat, Inc.




[Index of Archives]     [Selinux Refpolicy]     [Linux SGX]     [Fedora Users]     [Fedora Desktop]     [Yosemite Photos]     [Yosemite Camping]     [Yosemite Campsites]     [KDE Users]     [Gnome Users]

  Powered by Linux