public inbox for git-commits@fedoraproject.org
help / color / mirror / Atom feed
From: Ondrej Mosnacek <omosnace@redhat.com>
To: git-commits@fedoraproject.org
Subject: [tests/selinux] pr775-checkpolicy-revdeps: Add a test for two-way SCTP association setup
Date: Fri, 11 Sep 2026 13:19:38 GMT [thread overview]
Message-ID: <178913277878.1.3419069863410892661.tests-selinux-7b6ee73ecbf3@fedoraproject.org> (raw)
A new commit has been pushed.
Repo : tests/selinux
Branch : pr775-checkpolicy-revdeps
Commit : 7b6ee73ecbf37c183dea55e663d717ae469f61bf
Author : Ondrej Mosnacek <omosnace@redhat.com>
Date : 2022-02-13T21:14:49+01:00
Stats : +754/-0 in 7 file(s)
URL : https://src.fedoraproject.org/tests/selinux/c/7b6ee73ecbf37c183dea55e663d717ae469f61bf?branch=pr775-checkpolicy-revdeps
Log:
Add a test for two-way SCTP association setup
This test reproduces a bug that may cause an AVC with sctp_socket,
association, unlabeled_t, unlabeled_t (and also another bug related to
SCTP peeloff on the client side).
SCTP code taken and modified from selinux-testsuite's sctp subtest.
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---
diff --git a/kernel/sctp_peer_label_bug/Makefile b/kernel/sctp_peer_label_bug/Makefile
new file mode 100644
index 0000000..30c86c8
--- /dev/null
+++ b/kernel/sctp_peer_label_bug/Makefile
@@ -0,0 +1,8 @@
+# Minimal Makefile for standard-test-roles-beakerlib
+
+R="Requires: kernel-modules-extra"
+R="RhtsRequires: make gcc lksctp-tools-devel audit kernel-modules"
+
+run:
+ chmod +x runtest.sh
+ ./runtest.sh
diff --git a/kernel/sctp_peer_label_bug/main.fmf b/kernel/sctp_peer_label_bug/main.fmf
new file mode 100644
index 0000000..ae87830
--- /dev/null
+++ b/kernel/sctp_peer_label_bug/main.fmf
@@ -0,0 +1,25 @@
+summary: Verify that two-way SCTP association setup doesn't trigger AVCs
+description: |
+ Verify that two-way SCTP association setup doesn't trigger AVCs.
+contact: Ondrej Mosnacek <omosnace@redhat.com>
+component:
+ - kernel
+framework: beakerlib
+require:
+ - make
+ - gcc
+ - lksctp-tools-devel
+ - audit
+ - kernel-modules
+recommend:
+ - kernel-modules-extra
+duration: 10m
+tier: 2
+enabled: true
+adjust:
+ - enabled: false
+ when: distro < rhel-8
+ because: RHEL-7 and below don't have SCTP SELinux support
+link:
+ - verifies: https://bugzilla.redhat.com/show_bug.cgi?id=2048251
+ - verifies: https://bugzilla.redhat.com/show_bug.cgi?id=2015525
diff --git a/kernel/sctp_peer_label_bug/runtest.sh b/kernel/sctp_peer_label_bug/runtest.sh
new file mode 100755
index 0000000..22d2150
--- /dev/null
+++ b/kernel/sctp_peer_label_bug/runtest.sh
@@ -0,0 +1,61 @@
+#!/bin/bash
+# vim: dict=/usr/share/beakerlib/dictionary.vim cpt=.,w,b,u,t,i,k
+# SPDX-License-Identifier: GPLv2
+# Copyright (c) 2022 Red Hat, Inc.
+# Author: Ondrej Mosnacek <omosnace@redhat.com>
+
+# Include Beakerlib environment
+. /usr/share/beakerlib/beakerlib.sh || exit 1
+
+function check_avc_begin() {
+ sleep 1.1
+ date +'%x %T'
+ sleep 1.1
+}
+
+function check_avc_end() {
+ marker="marker-$RANDOM"
+
+ auditctl -m "$marker"
+
+ for (( i = 0; i < 100; i++ )); do
+ if ausearch -i -m user -ts $1 2>/dev/null </dev/null | \
+ grep -q "$marker"
+ then
+ echo $i
+ break
+ fi
+ sleep 0.1
+ done
+
+ ausearch -i -m avc -ts $1 </dev/null
+}
+
+rlJournalStart
+ rlPhaseStartSetup
+ rlRun "uname -r" 0 "Print kernel version"
+
+ for prog in sctp_bz2048251_client sctp_bz2048251_server; do
+ rlRun "gcc -O2 -Wall -o $prog sctp_common.c $prog.c -lsctp" 0 \
+ "Compile $prog"
+ done
+ rlRun "modprobe sctp" 0 "Ensure SCTP module is loaded"
+ rlRun "mkfifo flag" 0 "Create a fifo file for test"
+ rlPhaseEnd
+
+ rlPhaseStartTest
+ rlRun "audit_ts=\"\$(check_avc_begin)\""
+
+ rlRun "./sctp_bz2048251_server -f flag -4 9999 &" 0 "Start the server"
+ rlRun "read -t 5 <>flag" 0 "Wait for the server to start listening"
+ rlRun "./sctp_bz2048251_client 127.0.0.1 9999" 0 "Run the client"
+ rlRun "wait" 0 "Wait for the server to exit"
+
+ rlRun "check_avc_end \"\$audit_ts\"" 1 "Check if there are AVC denials"
+ rlPhaseEnd
+
+ rlPhaseStartCleanup
+ rlRun "rm -f sctp_bz2048251_client sctp_bz2048251_server flag"
+ rlPhaseEnd
+rlJournalPrintText
+rlJournalEnd
diff --git a/kernel/sctp_peer_label_bug/sctp_bz2048251_client.c b/kernel/sctp_peer_label_bug/sctp_bz2048251_client.c
new file mode 100644
index 0000000..03fbd09
--- /dev/null
+++ b/kernel/sctp_peer_label_bug/sctp_bz2048251_client.c
@@ -0,0 +1,109 @@
+#include "sctp_common.h"
+
+static void usage(char *progname)
+{
+ fprintf(stderr,
+ "usage: %s [-v] addr port\n"
+ "\nWhere:\n\t"
+
+ "-v Print context and ip options information.\n\t"
+ "addr IPv4 or IPv6 address (e.g. 127.0.0.1 or ::1).\n\t"
+ "port Port for accessing server.\n", progname);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int opt, sock, result;
+ struct addrinfo hints, *serverinfo;
+ bool verbose = false;
+ struct timeval tm;
+ socklen_t sinlen;
+ struct sockaddr_storage sin;
+
+ while ((opt = getopt(argc, argv, "v")) != -1) {
+ switch (opt) {
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ if ((argc - optind) != 2)
+ usage(argv[0]);
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_protocol = IPPROTO_SCTP;
+ hints.ai_socktype = SOCK_SEQPACKET;
+
+ result = getaddrinfo(argv[optind], argv[optind + 1], &hints,
+ &serverinfo);
+ if (result < 0) {
+ fprintf(stderr, "Client getaddrinfo: %s\n",
+ gai_strerror(result));
+ exit(2);
+ }
+
+ sock = socket(serverinfo->ai_family, serverinfo->ai_socktype,
+ serverinfo->ai_protocol);
+ if (sock < 0) {
+ perror("Client socket");
+ exit(3);
+ }
+
+ /*
+ * These timeouts are set to test whether the peer { recv } completes
+ * or not when the permission is denied.
+ */
+ tm.tv_sec = 4;
+ tm.tv_usec = 0;
+ result = setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tm, sizeof(tm));
+ if (result < 0) {
+ perror("Client setsockopt: SO_SNDTIMEO");
+ exit(4);
+ }
+
+ result = setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tm, sizeof(tm));
+ if (result < 0) {
+ perror("Client setsockopt: SO_RCVTIMEO");
+ exit(5);
+ }
+
+ if (listen(sock, SOMAXCONN)) {
+ perror("Client listen");
+ close(sock);
+ exit(1);
+ }
+
+ /* Subscribe to assoc_id events */
+ result = set_subscr_events(sock, off, on, off, off);
+ if (result < 0) {
+ perror("Client setsockopt: SCTP_EVENTS");
+ return 1;
+ }
+
+ result = open_assoc(sock, serverinfo->ai_addr, serverinfo->ai_addrlen,
+ verbose);
+ if (result) {
+ close(sock);
+ exit(result);
+ }
+
+ result = receive_assoc(sock, &sin, &sinlen, verbose);
+ if (result) {
+ close(sock);
+ exit(result);
+ }
+
+ result = open_assoc(sock, serverinfo->ai_addr, serverinfo->ai_addrlen,
+ verbose);
+ if (result) {
+ close(sock);
+ exit(result);
+ }
+
+ close(sock);
+ exit(0);
+}
diff --git a/kernel/sctp_peer_label_bug/sctp_bz2048251_server.c b/kernel/sctp_peer_label_bug/sctp_bz2048251_server.c
new file mode 100644
index 0000000..bf47257
--- /dev/null
+++ b/kernel/sctp_peer_label_bug/sctp_bz2048251_server.c
@@ -0,0 +1,132 @@
+#include "sctp_common.h"
+
+static void usage(char *progname)
+{
+ fprintf(stderr,
+ "usage: %s [-4] [-f file] [-v] port\n"
+ "\nWhere:\n\t"
+ "-4 Listen on IPv4 addresses only.\n\t"
+ "-f Write a line to the file when listening starts.\n\t"
+ " \"nopeer\" message to client, otherwise the peer context\n\t"
+ " will be retrieved and sent to client.\n\t"
+ "-v Print context and ip options information.\n\t"
+ "port Listening port.\n", progname);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ int opt, sock, result;
+ socklen_t sinlen;
+ struct sockaddr_storage sin;
+ struct addrinfo hints, *res;
+ char *flag_file = NULL;
+ bool verbose = false, ipv4 = false;
+ unsigned short port;
+
+ while ((opt = getopt(argc, argv, "4f:v")) != -1) {
+ switch (opt) {
+ case '4':
+ ipv4 = true;
+ break;
+ case 'f':
+ flag_file = optarg;
+ break;
+ case 'v':
+ verbose = true;
+ break;
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ if ((argc - optind) != 1)
+ usage(argv[0]);
+
+ port = atoi(argv[optind]);
+ if (!port)
+ usage(argv[0]);
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_protocol = IPPROTO_SCTP;
+
+ if (ipv4)
+ hints.ai_family = AF_INET;
+ else
+ hints.ai_family = AF_INET6;
+
+ /* sctp_peeloff(3) must be from 1 to Many style socket */
+ hints.ai_socktype = SOCK_SEQPACKET;
+
+ result = getaddrinfo(NULL, argv[optind], &hints, &res);
+ if (result < 0) {
+ fprintf(stderr, "Server getaddrinfo: %s\n",
+ gai_strerror(result));
+ exit(1);
+ }
+
+ sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+ if (sock < 0) {
+ perror("Server socket");
+ exit(1);
+ }
+
+ result = setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+ if (result < 0) {
+ perror("Server setsockopt: SO_REUSEADDR");
+ close(sock);
+ exit(1);
+ }
+
+ result = bind(sock, res->ai_addr, res->ai_addrlen);
+ if (result < 0) {
+ perror("Server bind");
+ close(sock);
+ exit(1);
+ }
+
+ if (listen(sock, SOMAXCONN)) {
+ perror("Server listen");
+ close(sock);
+ exit(1);
+ }
+
+ if (flag_file) {
+ FILE *f = fopen(flag_file, "w");
+ if (!f) {
+ perror("Flag file open");
+ exit(1);
+ }
+ fprintf(f, "listening\n");
+ fclose(f);
+ }
+
+ /* Subscribe to assoc_id events */
+ result = set_subscr_events(sock, off, on, off, off);
+ if (result < 0) {
+ perror("Client setsockopt: SCTP_EVENTS");
+ return 1;
+ }
+
+ result = receive_assoc(sock, &sin, &sinlen, verbose);
+ if (result) {
+ close(sock);
+ exit(result);
+ }
+
+ result = open_assoc(sock, (struct sockaddr *)&sin, sinlen, verbose);
+ if (result) {
+ close(sock);
+ exit(result);
+ }
+
+ result = receive_assoc(sock, &sin, &sinlen, verbose);
+ if (result) {
+ close(sock);
+ exit(result);
+ }
+
+ close(sock);
+ exit(0);
+}
diff --git a/kernel/sctp_peer_label_bug/sctp_common.c b/kernel/sctp_peer_label_bug/sctp_common.c
new file mode 100644
index 0000000..99ab7cb
--- /dev/null
+++ b/kernel/sctp_peer_label_bug/sctp_common.c
@@ -0,0 +1,381 @@
+#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_addr_info(struct sockaddr *sin, char *text)
+{
+ struct sockaddr_in *addr4;
+ struct sockaddr_in6 *addr6;
+ char addr_str[INET6_ADDRSTRLEN + 1];
+
+ switch (sin->sa_family) {
+ case AF_INET:
+ addr4 = (struct sockaddr_in *)sin;
+ inet_ntop(sin->sa_family,
+ (void *)&addr4->sin_addr,
+ addr_str, INET6_ADDRSTRLEN + 1);
+ printf("%s IPv4 addr %s\n", text, addr_str);
+ break;
+ case AF_INET6:
+ addr6 = (struct sockaddr_in6 *)sin;
+ if (IN6_IS_ADDR_V4MAPPED(&addr6->sin6_addr)) {
+ inet_ntop(AF_INET,
+ (void *)&addr6->sin6_addr.s6_addr32[3],
+ addr_str, INET6_ADDRSTRLEN + 1);
+ printf("%s IPv6->IPv4 MAPPED addr %s\n",
+ text, addr_str);
+ } else if (IN6_IS_ADDR_LINKLOCAL(&addr6->sin6_addr)) {
+ inet_ntop(sin->sa_family,
+ (void *)&addr6->sin6_addr,
+ addr_str, INET6_ADDRSTRLEN + 1);
+ printf("%s IPv6 local link addr %s scope_id %d\n",
+ text, addr_str,
+ ((struct sockaddr_in6 *)addr6)->sin6_scope_id);
+ } else {
+ inet_ntop(sin->sa_family,
+ (void *)&addr6->sin6_addr,
+ addr_str, INET6_ADDRSTRLEN + 1);
+ printf("%s IPv6 addr %s\n", text,
+ addr_str);
+ }
+ break;
+ default:
+ printf("%s Unknown IP family %d\n", text, sin->sa_family);
+ break;
+ }
+}
+
+int set_subscr_events(int fd, int data_io, int assoc, int addr, int shutd)
+{
+ 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 = assoc;
+ subscr_events.sctp_address_event = addr;
+ subscr_events.sctp_shutdown_event = shutd;
+
+ /*
+ * 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_shutdown_event));
+}
+
+/*
+ * Currently only SCTP_ASSOC_CHANGE, SCTP_PEER_ADDR_CHANGE and
+ * SCTP_SHUTDOWN_EVENT are enabled via set_subscr_events().
+ */
+int handle_event(void *buf, char *cmp_addr, sctp_assoc_t *assoc_id,
+ bool verbose, char *text)
+{
+ union sctp_notification *snp = buf;
+ char addrbuf[INET6_ADDRSTRLEN];
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ const char *ap;
+ struct sctp_paddr_change *spc;
+ struct sctp_assoc_change *sac;
+ struct sctp_remote_error *sre;
+ struct sctp_send_failed *ssf;
+ struct sctp_authkey_event *auth_event;
+
+ switch (snp->sn_header.sn_type) {
+ case SCTP_ASSOC_CHANGE:
+ sac = &snp->sn_assoc_change;
+
+ if (verbose)
+ printf("%s SCTP_ASSOC_CHANGE event for assoc_id: %d ERR: 0x%x\n",
+ text, sac->sac_assoc_id, sac->sac_error);
+
+ if (assoc_id)
+ *assoc_id = sac->sac_assoc_id;
+ break;
+ case SCTP_PEER_ADDR_CHANGE:
+ spc = &snp->sn_paddr_change;
+
+ if (verbose)
+ /*
+ * Not all spc_error codes are errors - linux/sctp.h
+ * (e.g. SCTP_HEARTBEAT_SUCCESS = 0x02)
+ */
+ printf("%s SCTP_PEER_ADDR_CHANGE event for assoc_id: %d ERR: 0x%x\n",
+ text, spc->spc_assoc_id, spc->spc_error);
+
+ if (spc->spc_aaddr.ss_family == AF_INET) {
+ sin = (struct sockaddr_in *) &spc->spc_aaddr;
+ ap = inet_ntop(AF_INET, &sin->sin_addr, addrbuf,
+ INET6_ADDRSTRLEN);
+ } else {
+ sin6 = (struct sockaddr_in6 *) &spc->spc_aaddr;
+ ap = inet_ntop(AF_INET6, &sin6->sin6_addr, addrbuf,
+ INET6_ADDRSTRLEN);
+ }
+ if (verbose) /* Print additional address details */
+ print_addr_info((struct sockaddr *)&spc->spc_aaddr,
+ "Peer Address change:\n\t");
+
+ switch (spc->spc_state) {
+ case SCTP_ADDR_AVAILABLE:
+ if (verbose)
+ printf("\t%s is available\n", text);
+ break;
+ case SCTP_ADDR_UNREACHABLE:
+ if (verbose)
+ printf("\t%s is not available - Error: 0x%x\n",
+ text, spc->spc_error);
+ break;
+ case SCTP_ADDR_REMOVED:
+ if (verbose)
+ printf("\t%s was removed\n", text);
+ break;
+ case SCTP_ADDR_ADDED:
+ if (verbose)
+ printf("\t%s was added\n", text);
+ break;
+ case SCTP_ADDR_MADE_PRIM:
+ if (verbose)
+ printf("\t%s is primary\n", text);
+ if (cmp_addr) {
+ if (!strcmp(ap, cmp_addr)) {
+ if (verbose)
+ printf("\t%s and is now the new primary\n", text);
+
+ return EVENT_ADDR_MATCH;
+ }
+ }
+ break;
+ case SCTP_ADDR_CONFIRMED:
+ if (verbose)
+ printf("\t%s is confirmed\n", text);
+ break;
+ default:
+ if (verbose)
+ printf("%s unknown state: %d\n", text,
+ spc->spc_state);
+ break;
+ }
+ break;
+ case SCTP_SEND_FAILED:
+ ssf = &snp->sn_send_failed;
+
+ if (verbose)
+ printf("%s SCTP_SEND_FAILED event assoc_id: %d ERR: 0x%x\n",
+ text, ssf->ssf_assoc_id, ssf->ssf_error);
+ break;
+ case SCTP_REMOTE_ERROR:
+ sre = &snp->sn_remote_error;
+ if (verbose) /* Error in network byte order - linux/sctp.h */
+ printf("%s SCTP_REMOTE_ERROR event ERR: 0x%x\n",
+ text, ntohs(sre->sre_error));
+ break;
+ case SCTP_SHUTDOWN_EVENT:
+ if (verbose)
+ printf("%s SCTP_SHUTDOWN_EVENT\n", text);
+
+ return EVENT_SHUTDOWN;
+ case SCTP_PARTIAL_DELIVERY_EVENT:
+ if (verbose)
+ printf("%s SCTP_PARTIAL_DELIVERY_EVENT\n", text);
+ break;
+ case SCTP_ADAPTATION_INDICATION:
+ if (verbose)
+ printf("%s SCTP_ADAPTATION_INDICATION event\n", text);
+ break;
+ case SCTP_AUTHENTICATION_INDICATION:
+ auth_event = &snp->sn_authkey_event;
+
+ if (verbose) {
+ printf("%s SCTP_AUTHENTICATION_INDICATION event\n"
+ "\tauth_event->auth_type: 0x%x\n"
+ "\tauth_event->auth_flags: 0x%x\n"
+ "\tauth_event->auth_length: 0x%x\n"
+ "\tauth_event->auth_keynumber: 0x%x\n"
+ "\tauth_event->auth_indication: 0x%x\n"
+ "\tauth_event->auth_assoc_id: %d\n",
+ text, auth_event->auth_type,
+ auth_event->auth_flags,
+ auth_event->auth_length,
+ auth_event->auth_keynumber,
+ auth_event->auth_indication,
+ auth_event->auth_assoc_id);
+ }
+ /* SCTP_AUTH_NO_AUTH defined in linux/sctp.h */
+ if (auth_event->auth_indication == SCTP_AUTH_NO_AUTH)
+ return EVENT_NO_AUTH;
+ break;
+ case SCTP_SENDER_DRY_EVENT:
+ if (verbose)
+ printf("%s SCTP_SENDER_DRY_EVENT\n", text);
+ break;
+ case SCTP_STREAM_RESET_EVENT:
+ if (verbose)
+ printf("%s SCTP_STREAM_RESET_EVENT\n", text);
+ break;
+ case SCTP_ASSOC_RESET_EVENT:
+ if (verbose)
+ printf("%s SCTP_ASSOC_RESET_EVENT\n", text);
+ break;
+ case SCTP_STREAM_CHANGE_EVENT:
+ if (verbose)
+ printf("%s SCTP_STREAM_CHANGE_EVENT\n", text);
+ break;
+ case SCTP_SEND_FAILED_EVENT:
+ if (verbose)
+ printf("%s SCTP_SEND_FAILED_EVENT\n", text);
+ break;
+ default:
+ fprintf(stderr, "%s unknown event: 0x%x\n", text,
+ snp->sn_header.sn_type);
+ break;
+ }
+
+ return EVENT_OK;
+}
+
+int receive_assoc(int sock, struct sockaddr_storage *sin, socklen_t *sinlen,
+ int verbose)
+{
+ int result, peeloff_sk = 0, flags;
+ sctp_assoc_t assoc_id = 0;
+ char *peerlabel, msglabel[256];
+
+ *sinlen = sizeof(*sin);
+ flags = 0;
+
+ result = sctp_recvmsg(sock, msglabel, sizeof(msglabel),
+ (struct sockaddr *)sin, sinlen,
+ NULL, &flags);
+ if (result < 0) {
+ perror("Server sctp_recvmsg-1");
+ return 1;
+ }
+
+ if (verbose)
+ print_addr_info((struct sockaddr *)sin,
+ "Server SEQPACKET recvmsg");
+
+ if (!(flags & MSG_NOTIFICATION) || !(flags & MSG_EOR)) {
+ printf("Invalid sctp_recvmsg response FLAGS: %x\n",
+ flags);
+ return 1;
+ }
+
+ handle_event(msglabel, NULL, &assoc_id,
+ verbose, "Peeloff Server");
+ if (assoc_id <= 0) {
+ printf("Server Invalid association ID: %d\n",
+ assoc_id);
+ return 1;
+ }
+ peeloff_sk = sctp_peeloff(sock, assoc_id);
+ if (peeloff_sk < 0) {
+ perror("Server sctp_peeloff");
+ return 1;
+ }
+ if (verbose) {
+ printf("Server sctp_peeloff(3) on sk: %d with association ID: %d\n",
+ peeloff_sk, assoc_id);
+ }
+
+ /* Now get the client msg on peeloff socket */
+ result = sctp_recvmsg(peeloff_sk, msglabel, sizeof(msglabel),
+ (struct sockaddr *)sin, sinlen,
+ NULL, &flags);
+ if (result < 0) {
+ perror("Server sctp_recvmsg-2");
+ close(peeloff_sk);
+ return 1;
+ }
+
+ if (verbose) {
+ print_addr_info((struct sockaddr *)sin,
+ "Server SEQPACKET peeloff recvmsg");
+ printf("peeloff association ID: %d\n",
+ assoc_id);
+ }
+
+ peerlabel = strdup("nopeer");
+
+ printf("Server PEELOFF peer label: %s\n", peerlabel);
+
+ result = sctp_sendmsg(peeloff_sk, peerlabel,
+ strlen(peerlabel),
+ NULL, 0,
+ 0, 0, 0, 0, 0);
+ if (result < 0) {
+ perror("Server sctp_sendmsg");
+ close(peeloff_sk);
+ close(sock);
+ exit(1);
+ }
+
+ if (verbose)
+ printf("Server PEELOFF sent: %s\n", peerlabel);
+
+ free(peerlabel);
+
+ close(peeloff_sk);
+ return 0;
+}
+
+int open_assoc(int sock, struct sockaddr *sin, socklen_t sinlen,
+ int verbose)
+{
+ int result, peeloff_sk = 0, flags;
+ sctp_assoc_t assoc_id = 0;
+ char byte = 0x41, label[1024];
+
+ result = connect(sock, sin, sinlen);
+ if (result < 0) {
+ perror("Client connect");
+ return 1;
+ }
+
+ /* Get assoc_id for sctp_peeloff() */
+ flags = 0;
+ result = sctp_recvmsg(sock, label, sizeof(label),
+ NULL, 0, NULL, &flags);
+ if (result < 0) {
+ perror("Client sctp_recvmsg-1");
+ return 1;
+ }
+
+ if ((flags & (MSG_NOTIFICATION | MSG_EOR)) != (MSG_NOTIFICATION | MSG_EOR)) {
+ printf("Invalid sctp_recvmsg response FLAGS: %x\n", flags);
+ return 1;
+ }
+ handle_event(label, NULL, &assoc_id, verbose, "Peeloff Client");
+ if (assoc_id <= 0) {
+ printf("Client Invalid association ID: %d\n", assoc_id);
+ return 1;
+ }
+
+ peeloff_sk = sctp_peeloff(sock, assoc_id);
+ if (peeloff_sk < 0) {
+ perror("Client sctp_peeloff");
+ return 1;
+ }
+
+ result = sctp_sendmsg(peeloff_sk, &byte, 1, NULL, 0,
+ 0, 0, 0, 0, 0);
+ if (result < 0) {
+ perror("Client sctp_sendmsg");
+ close(peeloff_sk);
+ return 1;
+ }
+
+ result = sctp_recvmsg(peeloff_sk, label, sizeof(label),
+ NULL, 0, NULL, NULL);
+ if (result < 0) {
+ perror("Client sctp_recvmsg");
+ close(peeloff_sk);
+ return 1;
+ }
+
+ close(peeloff_sk);
+ return 0;
+}
diff --git a/kernel/sctp_peer_label_bug/sctp_common.h b/kernel/sctp_peer_label_bug/sctp_common.h
new file mode 100644
index 0000000..aeec4d2
--- /dev/null
+++ b/kernel/sctp_peer_label_bug/sctp_common.h
@@ -0,0 +1,38 @@
+#ifndef _GNU_SOURCE
+#define _GNU_SOURCE /* For poll(2) POLLRDHUP - Detect client close(2) */
+#endif
+
+#include <arpa/inet.h>
+#include <sys/poll.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <netinet/ip.h>
+#include <netinet/sctp.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdbool.h>
+#include <errno.h>
+
+enum event_ret {
+ EVENT_OK,
+ EVENT_ADDR_MATCH,
+ EVENT_SHUTDOWN,
+ EVENT_NO_AUTH
+};
+
+void print_addr_info(struct sockaddr *sin, char *text);
+int set_subscr_events(int fd, int data_io, int assoc, int addr, int shutd);
+int handle_event(void *buf, char *cmp_addr, sctp_assoc_t *assoc_id,
+ bool verbose, char *text);
+
+static const int on = 1, off = 0;
+
+int receive_assoc(int sock, struct sockaddr_storage *sin, socklen_t *sinlen,
+ int verbose);
+int open_assoc(int sock, struct sockaddr *sin, socklen_t sinlen, int verbose);
next reply other threads:[~2026-09-11 13:19 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-11 13:19 Ondrej Mosnacek [this message]
2026-09-11 13:21 [tests/selinux] pr775-checkpolicy-revdeps: Add a test for two-way SCTP association setup Ondrej Mosnacek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=178913277878.1.3419069863410892661.tests-selinux-7b6ee73ecbf3@fedoraproject.org \
--to=omosnace@redhat.com \
--cc=git-commits@fedoraproject.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox