Browse Source

dccp: allow probing of CCID-array length

This fixes a problem in the DCCP getsockopt() API: currently there is no way
for a user to a priori know the number of built-in CCIDs, other than trying
DCCP_SOCKOPT_AVAILABLE_CCIDS in a loop, incrementing the option length until
EINVAL is no longer returned.

This patch truncates the array to the user-provided length. No copy is made
when the length is <= 0.

Due to the length restriction in do_dccp_getsockopt() to sizeof(int), the
minimum array length remains 4, which is a reasonable default (only 3
CCIDs, CCID-2..4, are currently defined).

Signed-off-by: Gerrit Renker <gerrit@erg.abdn.ac.uk>
Signed-off-by: David S. Miller <davem@davemloft.net>
Gerrit Renker 15 years ago
parent
commit
69a6a0b38a
2 changed files with 8 additions and 7 deletions
  1. 4 2
      Documentation/networking/dccp.txt
  2. 4 5
      net/dccp/ccid.c

+ 4 - 2
Documentation/networking/dccp.txt

@@ -58,8 +58,10 @@ DCCP_SOCKOPT_GET_CUR_MPS is read-only and retrieves the current maximum packet
 size (application payload size) in bytes, see RFC 4340, section 14.
 size (application payload size) in bytes, see RFC 4340, section 14.
 
 
 DCCP_SOCKOPT_AVAILABLE_CCIDS is also read-only and returns the list of CCIDs
 DCCP_SOCKOPT_AVAILABLE_CCIDS is also read-only and returns the list of CCIDs
-supported by the endpoint (see include/linux/dccp.h for symbolic constants).
-The caller needs to provide a sufficiently large (> 2) array of type uint8_t.
+supported by the endpoint. The option value is an array of type uint8_t whose
+size is passed as option length. The minimum array size is 4 elements, the
+value returned in the optlen argument always reflects the true number of
+built-in CCIDs.
 
 
 DCCP_SOCKOPT_CCID is write-only and sets both the TX and RX CCIDs at the same
 DCCP_SOCKOPT_CCID is write-only and sets both the TX and RX CCIDs at the same
 time, combining the operation of the next two socket options. This option is
 time, combining the operation of the next two socket options. This option is

+ 4 - 5
net/dccp/ccid.c

@@ -63,14 +63,13 @@ int ccid_getsockopt_builtin_ccids(struct sock *sk, int len,
 	u8 *ccid_array, array_len;
 	u8 *ccid_array, array_len;
 	int err = 0;
 	int err = 0;
 
 
-	if (len < ARRAY_SIZE(ccids))
-		return -EINVAL;
-
 	if (ccid_get_builtin_ccids(&ccid_array, &array_len))
 	if (ccid_get_builtin_ccids(&ccid_array, &array_len))
 		return -ENOBUFS;
 		return -ENOBUFS;
 
 
-	if (put_user(array_len, optlen) ||
-	    copy_to_user(optval, ccid_array, array_len))
+	if (put_user(array_len, optlen))
+		err = -EFAULT;
+	else if (len > 0 && copy_to_user(optval, ccid_array,
+					 len > array_len ? array_len : len))
 		err = -EFAULT;
 		err = -EFAULT;
 
 
 	kfree(ccid_array);
 	kfree(ccid_array);