]> www.infradead.org Git - users/willy/linux.git/commitdiff
sctp: Convert cookie authentication to use HMAC-SHA256
authorEric Biggers <ebiggers@kernel.org>
Mon, 18 Aug 2025 20:54:25 +0000 (13:54 -0700)
committerJakub Kicinski <kuba@kernel.org>
Wed, 20 Aug 2025 02:36:26 +0000 (19:36 -0700)
Convert SCTP cookies to use HMAC-SHA256, instead of the previous choice
of the legacy algorithms HMAC-MD5 and HMAC-SHA1.  Simplify and optimize
the code by using the HMAC-SHA256 library instead of crypto_shash, and
by preparing the HMAC key when it is generated instead of per-operation.

This doesn't break compatibility, since the cookie format is an
implementation detail, not part of the SCTP protocol itself.

Note that the cookie size doesn't change either.  The HMAC field was
already 32 bytes, even though previously at most 20 bytes were actually
compared.  32 bytes exactly fits an untruncated HMAC-SHA256 value.  So,
although we could safely truncate the MAC to something slightly shorter,
for now just keep the cookie size the same.

I also considered SipHash, but that would generate only 8-byte MACs.  An
8-byte MAC *might* suffice here.  However, there's quite a lot of
information in the SCTP cookies: more than in TCP SYN cookies.  So
absent an analysis that occasional forgeries of all that information is
okay in SCTP, I errored on the side of caution.

Remove HMAC-MD5 and HMAC-SHA1 as options, since the new HMAC-SHA256
option is just better.  It's faster as well as more secure.  For
example, benchmarking on x86_64, cookie authentication is now nearly 3x
as fast as the previous default choice and implementation of HMAC-MD5.

Also just make the kernel always support cookie authentication if SCTP
is supported at all, rather than making it optional in the build.  (It
was sort of optional before, but it didn't really work properly.  E.g.,
a kernel with CONFIG_SCTP_COOKIE_HMAC_MD5=n still supported HMAC-MD5
cookie authentication if CONFIG_CRYPTO_HMAC and CONFIG_CRYPTO_MD5
happened to be enabled in the kconfig for other reasons.)

Acked-by: Xin Long <lucien.xin@gmail.com>
Signed-off-by: Eric Biggers <ebiggers@kernel.org>
Link: https://patch.msgid.link/20250818205426.30222-5-ebiggers@kernel.org
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Documentation/networking/ip-sysctl.rst
include/net/netns/sctp.h
include/net/sctp/constants.h
include/net/sctp/structs.h
net/sctp/Kconfig
net/sctp/endpointola.c
net/sctp/protocol.c
net/sctp/sm_make_chunk.c
net/sctp/socket.c
net/sctp/sysctl.c

index 9756d16e3df1400626ce24726feceaeefa5da523..3d6782683eee746281526ab76064de05c5f0f8d6 100644 (file)
@@ -3508,16 +3508,13 @@ cookie_hmac_alg - STRING
        a listening sctp socket to a connecting client in the INIT-ACK chunk.
        Valid values are:
 
-       * md5
-       * sha1
+       * sha256
        * none
 
-       Ability to assign md5 or sha1 as the selected alg is predicated on the
-       configuration of those algorithms at build time (CONFIG_CRYPTO_MD5 and
-       CONFIG_CRYPTO_SHA1).
+       md5 and sha1 are also accepted for backwards compatibility, but cause
+       sha256 to be selected.
 
-       Default: Dependent on configuration.  MD5 if available, else SHA1 if
-       available, else none.
+       Default: sha256
 
 rcvbuf_policy - INTEGER
        Determines if the receive buffer is attributed to the socket or to
index d25cd7a9c5ff8747990694d8930f43971aed852f..c0f97f36389e6fed408419d3a0b1987bab102200 100644 (file)
@@ -75,8 +75,8 @@ struct netns_sctp {
        /* Whether Cookie Preservative is enabled(1) or not(0) */
        int cookie_preserve_enable;
 
-       /* The namespace default hmac alg */
-       char *sctp_hmac_alg;
+       /* Whether cookie authentication is enabled(1) or not(0) */
+       int cookie_auth_enable;
 
        /* Valid.Cookie.Life        - 60  seconds  */
        unsigned int valid_cookie_life;
index 8e0f4c4f7750662e6da367fe77e50ea70c1af54e..ae3376ba0b991e2fc6c1648b433ef83d70ad6161 100644 (file)
@@ -296,9 +296,8 @@ enum { SCTP_MAX_GABS = 16 };
                                         */
 #define SCTP_DEFAULT_MINSEGMENT 512    /* MTU size ... if no mtu disc */
 
-#define SCTP_SECRET_SIZE 32            /* Number of octets in a 256 bits. */
-
-#define SCTP_SIGNATURE_SIZE 20         /* size of a SLA-1 signature */
+#define SCTP_COOKIE_KEY_SIZE 32        /* size of cookie HMAC key */
+#define SCTP_COOKIE_MAC_SIZE 32        /* size of HMAC field in cookies */
 
 #define SCTP_COOKIE_MULTIPLE 32 /* Pad out our cookie to make our hash
                                 * functions simpler to write.
index 6be6aec25731eca8319254627a2d8ee55447cbcc..2ae390219efdd383c6656bbd71fa1dfabe6f7ae8 100644 (file)
@@ -32,6 +32,7 @@
 #ifndef __sctp_structs_h__
 #define __sctp_structs_h__
 
+#include <crypto/sha2.h>
 #include <linux/ktime.h>
 #include <linux/generic-radix-tree.h>
 #include <linux/rhashtable-types.h>
@@ -68,7 +69,6 @@ struct sctp_outq;
 struct sctp_bind_addr;
 struct sctp_ulpq;
 struct sctp_ep_common;
-struct crypto_shash;
 struct sctp_stream;
 
 
@@ -155,10 +155,6 @@ struct sctp_sock {
        /* PF_ family specific functions.  */
        struct sctp_pf *pf;
 
-       /* Access to HMAC transform. */
-       struct crypto_shash *hmac;
-       char *sctp_hmac_alg;
-
        /* What is our base endpointer? */
        struct sctp_endpoint *ep;
 
@@ -227,7 +223,8 @@ struct sctp_sock {
                frag_interleave:1,
                recvrcvinfo:1,
                recvnxtinfo:1,
-               data_ready_signalled:1;
+               data_ready_signalled:1,
+               cookie_auth_enable:1;
 
        atomic_t pd_mode;
 
@@ -335,7 +332,7 @@ struct sctp_cookie {
 
 /* The format of our cookie that we send to our peer. */
 struct sctp_signed_cookie {
-       __u8 signature[SCTP_SECRET_SIZE];
+       __u8 mac[SCTP_COOKIE_MAC_SIZE];
        __u32 __pad;            /* force sctp_cookie alignment to 64 bits */
        struct sctp_cookie c;
 } __packed;
@@ -1307,22 +1304,9 @@ struct sctp_endpoint {
        /* This is really a list of struct sctp_association entries. */
        struct list_head asocs;
 
-       /* Secret Key: A secret key used by this endpoint to compute
-        *            the MAC.  This SHOULD be a cryptographic quality
-        *            random number with a sufficient length.
-        *            Discussion in [RFC1750] can be helpful in
-        *            selection of the key.
-        */
-       __u8 secret_key[SCTP_SECRET_SIZE];
-
-       /* digest:  This is a digest of the sctp cookie.  This field is
-        *          only used on the receive path when we try to validate
-        *          that the cookie has not been tampered with.  We put
-        *          this here so we pre-allocate this once and can re-use
-        *          on every receive.
-        */
-       __u8 *digest;
+       /* Cookie authentication key used by this endpoint */
+       struct hmac_sha256_key cookie_auth_key;
+
        /* sendbuf acct. policy.        */
        __u32 sndbuf_policy;
 
index 09c77b4d161b12d5573d0d38af96e297034eb8c1..e947646a380cd3c62453619d9fc788fb8b2adaca 100644 (file)
@@ -49,48 +49,25 @@ config SCTP_DBG_OBJCNT
          'cat /proc/net/sctp/sctp_dbg_objcnt'
 
          If unsure, say N
+
 choice
-       prompt "Default SCTP cookie HMAC encoding"
-       default SCTP_DEFAULT_COOKIE_HMAC_MD5
+       prompt "Default SCTP cookie authentication method"
+       default SCTP_DEFAULT_COOKIE_HMAC_SHA256
        help
-         This option sets the default sctp cookie hmac algorithm
-         when in doubt select 'md5'
+         This option sets the default SCTP cookie authentication method, for
+         when a method hasn't been explicitly selected via the
+         net.sctp.cookie_hmac_alg sysctl.
 
-config SCTP_DEFAULT_COOKIE_HMAC_MD5
-       bool "Enable optional MD5 hmac cookie generation"
-       help
-         Enable optional MD5 hmac based SCTP cookie generation
-       select SCTP_COOKIE_HMAC_MD5
+         If unsure, choose the default (HMAC-SHA256).
 
-config SCTP_DEFAULT_COOKIE_HMAC_SHA1
-       bool "Enable optional SHA1 hmac cookie generation"
-       help
-         Enable optional SHA1 hmac based SCTP cookie generation
-       select SCTP_COOKIE_HMAC_SHA1
+config SCTP_DEFAULT_COOKIE_HMAC_SHA256
+       bool "HMAC-SHA256"
 
 config SCTP_DEFAULT_COOKIE_HMAC_NONE
-       bool "Use no hmac alg in SCTP cookie generation"
-       help
-         Use no hmac algorithm in SCTP cookie generation
+       bool "None"
 
 endchoice
 
-config SCTP_COOKIE_HMAC_MD5
-       bool "Enable optional MD5 hmac cookie generation"
-       help
-         Enable optional MD5 hmac based SCTP cookie generation
-       select CRYPTO
-       select CRYPTO_HMAC
-       select CRYPTO_MD5
-
-config SCTP_COOKIE_HMAC_SHA1
-       bool "Enable optional SHA1 hmac cookie generation"
-       help
-         Enable optional SHA1 hmac based SCTP cookie generation
-       select CRYPTO
-       select CRYPTO_HMAC
-       select CRYPTO_SHA1
-
 config INET_SCTP_DIAG
        depends on INET_DIAG
        def_tristate INET_DIAG
index 7e77b450697c094ff71b491f3295cad80abede02..31e989dfe84669174dfa3b1aa4593a513cfa9ac0 100644 (file)
 /* Forward declarations for internal helpers. */
 static void sctp_endpoint_bh_rcv(struct work_struct *work);
 
+static void gen_cookie_auth_key(struct hmac_sha256_key *key)
+{
+       u8 raw_key[SCTP_COOKIE_KEY_SIZE];
+
+       get_random_bytes(raw_key, sizeof(raw_key));
+       hmac_sha256_preparekey(key, raw_key, sizeof(raw_key));
+       memzero_explicit(raw_key, sizeof(raw_key));
+}
+
 /*
  * Initialize the base fields of the endpoint structure.
  */
@@ -45,10 +54,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
        struct net *net = sock_net(sk);
        struct sctp_shared_key *null_key;
 
-       ep->digest = kzalloc(SCTP_SIGNATURE_SIZE, gfp);
-       if (!ep->digest)
-               return NULL;
-
        ep->asconf_enable = net->sctp.addip_enable;
        ep->auth_enable = net->sctp.auth_enable;
        if (ep->auth_enable) {
@@ -90,8 +95,8 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
        /* Get the receive buffer policy for this endpoint */
        ep->rcvbuf_policy = net->sctp.rcvbuf_policy;
 
-       /* Initialize the secret key used with cookie. */
-       get_random_bytes(ep->secret_key, sizeof(ep->secret_key));
+       /* Generate the cookie authentication key. */
+       gen_cookie_auth_key(&ep->cookie_auth_key);
 
        /* SCTP-AUTH extensions*/
        INIT_LIST_HEAD(&ep->endpoint_shared_keys);
@@ -118,7 +123,6 @@ static struct sctp_endpoint *sctp_endpoint_init(struct sctp_endpoint *ep,
 nomem_shkey:
        sctp_auth_free(ep);
 nomem:
-       kfree(ep->digest);
        return NULL;
 
 }
@@ -205,9 +209,6 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
                return;
        }
 
-       /* Free the digest buffer */
-       kfree(ep->digest);
-
        /* SCTP-AUTH: Free up AUTH releated data such as shared keys
         * chunks and hmacs arrays that were allocated
         */
@@ -218,7 +219,7 @@ static void sctp_endpoint_destroy(struct sctp_endpoint *ep)
        sctp_inq_free(&ep->base.inqueue);
        sctp_bind_addr_free(&ep->base.bind_addr);
 
-       memset(ep->secret_key, 0, sizeof(ep->secret_key));
+       memzero_explicit(&ep->cookie_auth_key, sizeof(ep->cookie_auth_key));
 
        sk = ep->base.sk;
        /* Remove and free the port */
index a5ccada55f2b29cd478cc4c4699f93005301de07..3b2373b3bd5dfcc7f1368f392786c2dafa1938c3 100644 (file)
@@ -1334,14 +1334,9 @@ static int __net_init sctp_defaults_init(struct net *net)
        /* Whether Cookie Preservative is enabled(1) or not(0) */
        net->sctp.cookie_preserve_enable        = 1;
 
-       /* Default sctp sockets to use md5 as their hmac alg */
-#if defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_MD5)
-       net->sctp.sctp_hmac_alg                 = "md5";
-#elif defined (CONFIG_SCTP_DEFAULT_COOKIE_HMAC_SHA1)
-       net->sctp.sctp_hmac_alg                 = "sha1";
-#else
-       net->sctp.sctp_hmac_alg                 = NULL;
-#endif
+       /* Whether cookie authentication is enabled(1) or not(0) */
+       net->sctp.cookie_auth_enable =
+               !IS_ENABLED(CONFIG_SCTP_DEFAULT_COOKIE_HMAC_NONE);
 
        /* Max.Burst                - 4 */
        net->sctp.max_burst                     = SCTP_DEFAULT_MAX_BURST;
index a1a3c8494c5d22814fb9ec8bae06447cd76e189e..2c0017d058d409e6b019e5e97842b78110248fac 100644 (file)
@@ -30,7 +30,6 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <crypto/hash.h>
 #include <crypto/utils.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
@@ -1675,8 +1674,10 @@ static struct sctp_cookie_param *sctp_pack_cookie(
         * out on the network.
         */
        retval = kzalloc(*cookie_len, GFP_ATOMIC);
-       if (!retval)
-               goto nodata;
+       if (!retval) {
+               *cookie_len = 0;
+               return NULL;
+       }
 
        cookie = (struct sctp_signed_cookie *) retval->body;
 
@@ -1707,26 +1708,14 @@ static struct sctp_cookie_param *sctp_pack_cookie(
        memcpy((__u8 *)(cookie + 1) +
               ntohs(init_chunk->chunk_hdr->length), raw_addrs, addrs_len);
 
-       if (sctp_sk(ep->base.sk)->hmac) {
-               struct crypto_shash *tfm = sctp_sk(ep->base.sk)->hmac;
-               int err;
-
-               /* Sign the message.  */
-               err = crypto_shash_setkey(tfm, ep->secret_key,
-                                         sizeof(ep->secret_key)) ?:
-                     crypto_shash_tfm_digest(tfm, (u8 *)&cookie->c, bodysize,
-                                             cookie->signature);
-               if (err)
-                       goto free_cookie;
+       /* Sign the cookie, if cookie authentication is enabled. */
+       if (sctp_sk(ep->base.sk)->cookie_auth_enable) {
+               static_assert(sizeof(cookie->mac) == SHA256_DIGEST_SIZE);
+               hmac_sha256(&ep->cookie_auth_key, (const u8 *)&cookie->c,
+                           bodysize, cookie->mac);
        }
 
        return retval;
-
-free_cookie:
-       kfree(retval);
-nodata:
-       *cookie_len = 0;
-       return NULL;
 }
 
 /* Unpack the cookie from COOKIE ECHO chunk, recreating the association.  */
@@ -1741,7 +1730,6 @@ struct sctp_association *sctp_unpack_cookie(
        struct sctp_signed_cookie *cookie;
        struct sk_buff *skb = chunk->skb;
        struct sctp_cookie *bear_cookie;
-       __u8 *digest = ep->digest;
        enum sctp_scope scope;
        unsigned int len;
        ktime_t kt;
@@ -1771,30 +1759,19 @@ struct sctp_association *sctp_unpack_cookie(
        cookie = chunk->subh.cookie_hdr;
        bear_cookie = &cookie->c;
 
-       if (!sctp_sk(ep->base.sk)->hmac)
-               goto no_hmac;
+       /* Verify the cookie's MAC, if cookie authentication is enabled. */
+       if (sctp_sk(ep->base.sk)->cookie_auth_enable) {
+               u8 mac[SHA256_DIGEST_SIZE];
 
-       /* Check the signature.  */
-       {
-               struct crypto_shash *tfm = sctp_sk(ep->base.sk)->hmac;
-               int err;
-
-               err = crypto_shash_setkey(tfm, ep->secret_key,
-                                         sizeof(ep->secret_key)) ?:
-                     crypto_shash_tfm_digest(tfm, (u8 *)bear_cookie, bodysize,
-                                             digest);
-               if (err) {
-                       *error = -SCTP_IERROR_NOMEM;
+               hmac_sha256(&ep->cookie_auth_key, (const u8 *)bear_cookie,
+                           bodysize, mac);
+               static_assert(sizeof(cookie->mac) == sizeof(mac));
+               if (crypto_memneq(mac, cookie->mac, sizeof(mac))) {
+                       *error = -SCTP_IERROR_BAD_SIG;
                        goto fail;
                }
        }
 
-       if (crypto_memneq(digest, cookie->signature, SCTP_SIGNATURE_SIZE)) {
-               *error = -SCTP_IERROR_BAD_SIG;
-               goto fail;
-       }
-
-no_hmac:
        /* IG Section 2.35.2:
         *  3) Compare the port numbers and the verification tag contained
         *     within the COOKIE ECHO chunk to the actual port numbers and the
index 0292881a847ca0ed7a35be30f82717465c444ac0..ed8293a3424029a176721e01005d6929ea4b9ebd 100644 (file)
@@ -37,7 +37,6 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
-#include <crypto/hash.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/wait.h>
@@ -4987,7 +4986,7 @@ static int sctp_init_sock(struct sock *sk)
        sp->default_rcv_context = 0;
        sp->max_burst = net->sctp.max_burst;
 
-       sp->sctp_hmac_alg = net->sctp.sctp_hmac_alg;
+       sp->cookie_auth_enable = net->sctp.cookie_auth_enable;
 
        /* Initialize default setup parameters. These parameters
         * can be modified with the SCTP_INITMSG socket option or
@@ -5079,8 +5078,6 @@ static int sctp_init_sock(struct sock *sk)
        if (!sp->ep)
                return -ENOMEM;
 
-       sp->hmac = NULL;
-
        sk->sk_destruct = sctp_destruct_sock;
 
        SCTP_DBG_OBJCNT_INC(sock);
@@ -5117,18 +5114,8 @@ static void sctp_destroy_sock(struct sock *sk)
        sock_prot_inuse_add(sock_net(sk), sk->sk_prot, -1);
 }
 
-/* Triggered when there are no references on the socket anymore */
-static void sctp_destruct_common(struct sock *sk)
-{
-       struct sctp_sock *sp = sctp_sk(sk);
-
-       /* Free up the HMAC transform. */
-       crypto_free_shash(sp->hmac);
-}
-
 static void sctp_destruct_sock(struct sock *sk)
 {
-       sctp_destruct_common(sk);
        inet_sock_destruct(sk);
 }
 
@@ -8530,22 +8517,8 @@ static int sctp_listen_start(struct sock *sk, int backlog)
 {
        struct sctp_sock *sp = sctp_sk(sk);
        struct sctp_endpoint *ep = sp->ep;
-       struct crypto_shash *tfm = NULL;
-       char alg[32];
        int err;
 
-       /* Allocate HMAC for generating cookie. */
-       if (!sp->hmac && sp->sctp_hmac_alg) {
-               sprintf(alg, "hmac(%s)", sp->sctp_hmac_alg);
-               tfm = crypto_alloc_shash(alg, 0, 0);
-               if (IS_ERR(tfm)) {
-                       net_info_ratelimited("failed to load transform for %s: %ld\n",
-                                            sp->sctp_hmac_alg, PTR_ERR(tfm));
-                       return -ENOSYS;
-               }
-               sctp_sk(sk)->hmac = tfm;
-       }
-
        /*
         * If a bind() or sctp_bindx() is not called prior to a listen()
         * call that allows new associations to be accepted, the system
@@ -9561,7 +9534,6 @@ static int sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
         * copy.
         */
        newsp->ep = newep;
-       newsp->hmac = NULL;
 
        /* Hook this new socket in to the bind_hash list. */
        head = &sctp_port_hashtable[sctp_phashfn(sock_net(oldsk),
@@ -9713,7 +9685,6 @@ struct proto sctp_prot = {
 
 static void sctp_v6_destruct_sock(struct sock *sk)
 {
-       sctp_destruct_common(sk);
        inet6_sock_destruct(sk);
 }
 
index ee3eac338a9deef064f273e29bb59b057835d3f1..19acc57c3ed97fe7c3d8e16f29698ca4add40af5 100644 (file)
@@ -174,7 +174,7 @@ static struct ctl_table sctp_net_table[] = {
        },
        {
                .procname       = "cookie_hmac_alg",
-               .data           = &init_net.sctp.sctp_hmac_alg,
+               .data           = &init_net.sctp.cookie_auth_enable,
                .maxlen         = 8,
                .mode           = 0644,
                .proc_handler   = proc_sctp_do_hmac_alg,
@@ -388,10 +388,8 @@ static int proc_sctp_do_hmac_alg(const struct ctl_table *ctl, int write,
                                 void *buffer, size_t *lenp, loff_t *ppos)
 {
        struct net *net = container_of(ctl->data, struct net,
-                                      sctp.sctp_hmac_alg);
+                                      sctp.cookie_auth_enable);
        struct ctl_table tbl;
-       bool changed = false;
-       char *none = "none";
        char tmp[8] = {0};
        int ret;
 
@@ -399,35 +397,28 @@ static int proc_sctp_do_hmac_alg(const struct ctl_table *ctl, int write,
 
        if (write) {
                tbl.data = tmp;
-               tbl.maxlen = sizeof(tmp);
-       } else {
-               tbl.data = net->sctp.sctp_hmac_alg ? : none;
-               tbl.maxlen = strlen(tbl.data);
-       }
-
-       ret = proc_dostring(&tbl, write, buffer, lenp, ppos);
-       if (write && ret == 0) {
-#ifdef CONFIG_CRYPTO_MD5
-               if (!strncmp(tmp, "md5", 3)) {
-                       net->sctp.sctp_hmac_alg = "md5";
-                       changed = true;
+               tbl.maxlen = sizeof(tmp) - 1;
+               ret = proc_dostring(&tbl, 1, buffer, lenp, ppos);
+               if (ret)
+                       return ret;
+               if (!strcmp(tmp, "sha256") ||
+                   /* for backwards compatibility */
+                   !strcmp(tmp, "md5") || !strcmp(tmp, "sha1")) {
+                       net->sctp.cookie_auth_enable = 1;
+                       return 0;
                }
-#endif
-#ifdef CONFIG_CRYPTO_SHA1
-               if (!strncmp(tmp, "sha1", 4)) {
-                       net->sctp.sctp_hmac_alg = "sha1";
-                       changed = true;
+               if (!strcmp(tmp, "none")) {
+                       net->sctp.cookie_auth_enable = 0;
+                       return 0;
                }
-#endif
-               if (!strncmp(tmp, "none", 4)) {
-                       net->sctp.sctp_hmac_alg = NULL;
-                       changed = true;
-               }
-               if (!changed)
-                       ret = -EINVAL;
+               return -EINVAL;
        }
-
-       return ret;
+       if (net->sctp.cookie_auth_enable)
+               tbl.data = (char *)"sha256";
+       else
+               tbl.data = (char *)"none";
+       tbl.maxlen = strlen(tbl.data);
+       return proc_dostring(&tbl, 0, buffer, lenp, ppos);
 }
 
 static int proc_sctp_do_rto_min(const struct ctl_table *ctl, int write,