[bug report] rxrpc: rxgk: Implement the yfs-rxgk security class (GSSAPI)

Dan Carpenter dan.carpenter at linaro.org
Tue Sep 9 06:07:04 PDT 2025


Hello David Howells,

Commit 9d1d2b59341f ("rxrpc: rxgk: Implement the yfs-rxgk security
class (GSSAPI)") from Apr 11, 2025 (linux-next), leads to the
following (UNPUBLISHED) Smatch static checker warning:

	net/rxrpc/rxgk_app.c:65 rxgk_yfs_decode_ticket()
	warn: untrusted unsigned subtract. 'ticket_len - 10 * 4'

net/rxrpc/rxgk_app.c
    42 int rxgk_yfs_decode_ticket(struct rxrpc_connection *conn, struct sk_buff *skb,
    43                            unsigned int ticket_offset, unsigned int ticket_len,
    44                            struct key **_key)
    45 {
    46         struct rxrpc_key_token *token;
    47         const struct cred *cred = current_cred(); // TODO - use socket creds
    48         struct key *key;
    49         size_t pre_ticket_len, payload_len;
    50         unsigned int klen, enctype;
    51         void *payload, *ticket;
    52         __be32 *t, *p, *q, tmp[2];
    53         int ret;
    54 
    55         _enter("");
    56 
    57         /* Get the session key length */
    58         ret = skb_copy_bits(skb, ticket_offset, tmp, sizeof(tmp));
    59         if (ret < 0)
    60                 return rxrpc_abort_conn(conn, skb, RXGK_INCONSISTENCY, -EPROTO,
    61                                         rxgk_abort_resp_short_yfs_klen);
    62         enctype = ntohl(tmp[0]);
    63         klen = ntohl(tmp[1]);
    64 
--> 65         if (klen > ticket_len - 10 * sizeof(__be32))
                          ^^^^^^^^^^
I don't think we know that ticket_len is >= 40 so this bounds checking
might not work as intended.  Since it's unsigned then negative values
are treated as very high positive values.

    66                 return rxrpc_abort_conn(conn, skb, RXGK_INCONSISTENCY, -EPROTO,
    67                                         rxgk_abort_resp_short_yfs_key);
    68 

token_len is set in rxgk_verify_response().

net/rxrpc/rxgk.c
  1180  static int rxgk_verify_response(struct rxrpc_connection *conn,
  1181                                  struct sk_buff *skb)
  1182  {
  1183          const struct krb5_enctype *krb5;
  1184          struct rxrpc_key_token *token;
  1185          struct rxrpc_skb_priv *sp = rxrpc_skb(skb);
  1186          struct rxgk_response rhdr;
  1187          struct rxgk_context *gk;
  1188          struct key *key = NULL;
  1189          unsigned int offset = sizeof(struct rxrpc_wire_header);
  1190          unsigned int len = skb->len - sizeof(struct rxrpc_wire_header);
  1191          unsigned int token_offset, token_len;
  1192          unsigned int auth_offset, auth_len;
  1193          __be32 xauth_len;
  1194          int ret, ec;
  1195  
  1196          _enter("{%d}", conn->debug_id);
  1197  
  1198          /* Parse the RXGK_Response object */
  1199          if (sizeof(rhdr) + sizeof(__be32) > len)
  1200                  goto short_packet;
  1201  
  1202          if (skb_copy_bits(skb, offset, &rhdr, sizeof(rhdr)) < 0)
  1203                  goto short_packet;
  1204          offset  += sizeof(rhdr);
  1205          len     -= sizeof(rhdr);
  1206  
  1207          token_offset    = offset;
  1208          token_len       = ntohl(rhdr.token_len);
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  1209          if (xdr_round_up(token_len) + sizeof(__be32) > len)
  1210                  goto short_packet;

There is an upper bounds check but no lower bounds check.

  1211  
  1212          trace_rxrpc_rx_response(conn, sp->hdr.serial, 0, sp->hdr.cksum, token_len);
  1213  
  1214          offset  += xdr_round_up(token_len);
  1215          len     -= xdr_round_up(token_len);
  1216  
  1217          if (skb_copy_bits(skb, offset, &xauth_len, sizeof(xauth_len)) < 0)
  1218                  goto short_packet;
  1219          offset  += sizeof(xauth_len);
  1220          len     -= sizeof(xauth_len);
  1221  
  1222          auth_offset     = offset;
  1223          auth_len        = ntohl(xauth_len);
  1224          if (auth_len < len)
  1225                  goto short_packet;
  1226          if (auth_len & 3)
  1227                  goto inconsistent;
  1228          if (auth_len < 20 + 9 * 4)
  1229                  goto auth_too_short;
  1230  
  1231          /* We need to extract and decrypt the token and instantiate a session
  1232           * key for it.  This bit, however, is application-specific.  If
  1233           * possible, we use a default parser, but we might end up bumping this
  1234           * to the app to deal with - which might mean a round trip to
  1235           * userspace.
  1236           */
  1237          ret = rxgk_extract_token(conn, skb, token_offset, token_len, &key);
                                                                  ^^^^^^^^^

  1238          if (ret < 0)
  1239                  goto out;
  1240  

regards,
dan carpenter



More information about the linux-afs mailing list