Frank Sorensen recently noted that the Linux Client’s v3 size allocations for some operations may be incorrect. If that is the case, we’d expect to have reports of crashes, as this code is old. Let’s figure out what’s going on..

The question is why hasn’t anyone seen an overflow from req->rq_callsize:

1763 static void
1764 call_allocate(struct rpc_task *task)                                                                      
1765 {   
...
1784     /* 
1785      * Calculate the size (in quads) of the RPC call                                                      
1786      * and reply headers, and convert both values                                                         
1787      * to byte sizes.                                                                                     
1788      */
1789     req->rq_callsize = RPC_CALLHDRSIZE + (auth->au_cslack << 1) +                                         
1790                proc->p_arglen;                                                                            
1791     req->rq_callsize <<= 2;                                                                               
1792     /* 

RPC_CALLHDRSIZE is 6 quad words. This should cover:

  • unsigned int xid: 1
  • enum msg_type: 1
  • unsigned int rpcvers: 1
  • unsigned int prog: 1
  • unsigned int vers: 1
  • unsigned int proc: 1

After this, the client adds auth->au_cslack, which for AUTH_SYS is set as UNX_CALLSLACK:

include/linux/sunrpc/auth.h:#define UNX_CALLSLACK       (21 + XDR_QUADLEN(UNX_MAXNODENAME))

UNX_MAXNODENAME is __NEW_UTS_LEN is 64, which XDR_QUADLEN will take down to 16, so we have au_cslack of 37.

So, what are those 37 words? We now have an opaque_auth cred:

  • unsigned int flavor: 1
  • unsigned int length: 1

.. and then the AUTH_SYS cred body:

  • unsigned int stamp: 1
  • string machinename<255>: (linux only sends 64 bytes, so max here is 17):
    • unsigned int length: 1
    • body: 16
  • unsigned int uid: 1
  • unsigned int gid: 1
  • unsigned int gids<16>: 17

for up to 39 words, then the opaque_auth verifier:

  • auth_flavor: 1
  • length: 1

We ought then to be up to 41 words needed in au_cslack for AUTH_SYS, not 37. We are saved from having a problem by the fact that the current code left-shifts our 37 into 74. This is likely the reason why our miscalculations in procedure are not causing crashes.