Commit f31dddd2 authored by Yunqiang Su's avatar Yunqiang Su Committed by Laurent Vivier
Browse files

linux-user: Add support for setsockopt() option SOL_ALG



Add support for options SOL_ALG of the syscall setsockopt(). This
option is used in relation to Linux kernel Crypto API, and allows
a user to set additional information for the cipher operation via
syscall setsockopt(). The field "optname" must be one of the
following:

  - ALG_SET_KEY – seting the key
  - ALG_SET_AEAD_AUTHSIZE – set the authentication tag size

SOL_ALG is relatively newer setsockopt() option. Therefore, the
code that handles SOL_ALG is enclosed in "ifdef" so that the build
does not fail for older kernels that do not contain support for
SOL_ALG. "ifdef" also contains check if ALG_SET_KEY and
ALG_SET_AEAD_AUTHSIZE are defined.

Signed-off-by: default avatarYunqiang Su <ysu@wavecomp.com>
Signed-off-by: default avatarAleksandar Markovic <amarkovic@wavecomp.com>
Reviewed-by: default avatarLaurent Vivier <laurent@vivier.eu>
Message-Id: <1560953834-29584-3-git-send-email-aleksandar.markovic@rt-rk.com>
Signed-off-by: default avatarLaurent Vivier <laurent@vivier.eu>
parent 524fa340
Loading
Loading
Loading
Loading
+31 −0
Original line number Diff line number Diff line
@@ -102,6 +102,7 @@
#include <linux/blkpg.h>
#include <netpacket/packet.h>
#include <linux/netlink.h>
#include <linux/if_alg.h>
#include "linux_loop.h"
#include "uname.h"

@@ -1941,6 +1942,36 @@ static abi_long do_setsockopt(int sockfd, int level, int optname,
            goto unimplemented;
        }
        break;
#if defined(SOL_ALG) && defined(ALG_SET_KEY) && defined(ALG_SET_AEAD_AUTHSIZE)
    case SOL_ALG:
        switch (optname) {
        case ALG_SET_KEY:
        {
            char *alg_key = g_malloc(optlen);

            if (!alg_key) {
                return -TARGET_ENOMEM;
            }
            if (copy_from_user(alg_key, optval_addr, optlen)) {
                g_free(alg_key);
                return -TARGET_EFAULT;
            }
            ret = get_errno(setsockopt(sockfd, level, optname,
                                       alg_key, optlen));
            g_free(alg_key);
            break;
        }
        case ALG_SET_AEAD_AUTHSIZE:
        {
            ret = get_errno(setsockopt(sockfd, level, optname,
                                       NULL, optlen));
            break;
        }
        default:
            goto unimplemented;
        }
        break;
#endif
    case TARGET_SOL_SOCKET:
        switch (optname) {
        case TARGET_SO_RCVTIMEO: