mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-28 21:35:13 -04:00
Replace EXPORT_SYMBOL_FOR_MODULES() with EXPORT_SYMBOL_IF_KUNIT() to mark the symbols as visible only if CONFIG_KUNIT is enabled. Kunit test should import the namespace EXPORTED_FOR_KUNIT_TESTING to use these marked symbols. This is the standard way for all KUnit tests. Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Reviewed-by: ChenXiaoSong <chenxiaosong@kylinos.cn> Signed-off-by: Steve French <stfrench@microsoft.com>
287 lines
7.7 KiB
C
287 lines
7.7 KiB
C
// SPDX-License-Identifier: GPL-2.0-or-later
|
|
/*
|
|
*
|
|
* Copyright (c) International Business Machines Corp., 2002,2008
|
|
* Author(s): Steve French (sfrench@us.ibm.com)
|
|
*
|
|
* Error mapping routines from Samba libsmb/errormap.c
|
|
* Copyright (C) Andrew Tridgell 2001
|
|
* Copyright (C) Luke Kenneth Casson Leighton 1997-2001.
|
|
*/
|
|
|
|
#include <linux/bsearch.h>
|
|
|
|
#include <kunit/visibility.h>
|
|
|
|
#include "cifsproto.h"
|
|
#include "smb1proto.h"
|
|
#include "smberr.h"
|
|
#include "nterr.h"
|
|
#include "cifs_debug.h"
|
|
|
|
static __always_inline int smb1_posix_error_cmp(const void *_key, const void *_pivot)
|
|
{
|
|
__u16 key = *(__u16 *)_key;
|
|
const struct smb_to_posix_error *pivot = _pivot;
|
|
|
|
if (key < pivot->smb_err)
|
|
return -1;
|
|
if (key > pivot->smb_err)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
static const struct smb_to_posix_error mapping_table_ERRDOS[] = {
|
|
/*
|
|
* Automatically generated by the `gen_smb1_mapping` script,
|
|
* sorted by DOS error code (ascending).
|
|
*/
|
|
#include "smb1_err_dos_map.c"
|
|
};
|
|
|
|
static const struct smb_to_posix_error mapping_table_ERRSRV[] = {
|
|
/*
|
|
* Automatically generated by the `gen_smb1_mapping` script,
|
|
* sorted by SRV error code (ascending).
|
|
*/
|
|
#include "smb1_err_srv_map.c"
|
|
};
|
|
|
|
/*****************************************************************************
|
|
*convert a NT status code to a dos class/code
|
|
*****************************************************************************/
|
|
|
|
static __always_inline int ntstatus_to_dos_cmp(const void *_key, const void *_pivot)
|
|
{
|
|
__u32 key = *(__u32 *)_key;
|
|
const struct ntstatus_to_dos_err *pivot = _pivot;
|
|
|
|
if (key < pivot->ntstatus)
|
|
return -1;
|
|
if (key > pivot->ntstatus)
|
|
return 1;
|
|
return 0;
|
|
}
|
|
|
|
/* NT status -> dos error map */
|
|
static const struct ntstatus_to_dos_err ntstatus_to_dos_map[] = {
|
|
/*
|
|
* Automatically generated by the `gen_smb1_mapping` script,
|
|
* sorted by NT status code (ascending).
|
|
*/
|
|
#include "smb1_mapping_table.c"
|
|
};
|
|
|
|
static const struct ntstatus_to_dos_err *
|
|
search_ntstatus_to_dos_map(__u32 ntstatus)
|
|
{
|
|
return __inline_bsearch(&ntstatus, ntstatus_to_dos_map,
|
|
ARRAY_SIZE(ntstatus_to_dos_map),
|
|
sizeof(struct ntstatus_to_dos_err),
|
|
ntstatus_to_dos_cmp);
|
|
}
|
|
|
|
static const struct smb_to_posix_error *
|
|
search_mapping_table_ERRDOS(__u16 smb_err)
|
|
{
|
|
return __inline_bsearch(&smb_err, mapping_table_ERRDOS,
|
|
ARRAY_SIZE(mapping_table_ERRDOS),
|
|
sizeof(struct smb_to_posix_error),
|
|
smb1_posix_error_cmp);
|
|
}
|
|
|
|
static const struct smb_to_posix_error *
|
|
search_mapping_table_ERRSRV(__u16 smb_err)
|
|
{
|
|
return __inline_bsearch(&smb_err, mapping_table_ERRSRV,
|
|
ARRAY_SIZE(mapping_table_ERRSRV),
|
|
sizeof(struct smb_to_posix_error),
|
|
smb1_posix_error_cmp);
|
|
}
|
|
|
|
int
|
|
map_smb_to_linux_error(char *buf, bool logErr)
|
|
{
|
|
struct smb_hdr *smb = (struct smb_hdr *)buf;
|
|
int rc = -EIO; /* if transport error smb error may not be set */
|
|
__u8 smberrclass;
|
|
__u16 smberrcode;
|
|
const struct smb_to_posix_error *err_map = NULL;
|
|
|
|
/* BB if NT Status codes - map NT BB */
|
|
|
|
/* old style smb error codes */
|
|
if (smb->Status.CifsError == 0)
|
|
return 0;
|
|
|
|
if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
|
|
/* translate the newer STATUS codes to old style SMB errors
|
|
* and then to POSIX errors */
|
|
__u32 err = le32_to_cpu(smb->Status.CifsError);
|
|
const struct ntstatus_to_dos_err *map = search_ntstatus_to_dos_map(err);
|
|
|
|
if (map) {
|
|
if ((logErr && err != NT_STATUS_MORE_PROCESSING_REQUIRED) ||
|
|
(cifsFYI & CIFS_RC))
|
|
pr_notice("Status code returned 0x%08x %s\n",
|
|
map->ntstatus, map->nt_errstr);
|
|
|
|
smberrclass = map->dos_class;
|
|
smberrcode = map->dos_code;
|
|
} else {
|
|
smberrclass = ERRHRD;
|
|
smberrcode = ERRgeneral;
|
|
}
|
|
} else {
|
|
smberrclass = smb->Status.DosError.ErrorClass;
|
|
smberrcode = le16_to_cpu(smb->Status.DosError.Error);
|
|
}
|
|
|
|
/* old style errors */
|
|
|
|
if (smberrclass == ERRDOS) {
|
|
/* DOS class smb error codes - map DOS */
|
|
/* 1 byte field no need to byte reverse */
|
|
err_map = search_mapping_table_ERRDOS(smberrcode);
|
|
} else if (smberrclass == ERRSRV) {
|
|
/* server class of error codes */
|
|
err_map = search_mapping_table_ERRSRV(smberrcode);
|
|
}
|
|
if (err_map)
|
|
rc = err_map->posix_code;
|
|
/* else ERRHRD class errors or junk - return EIO */
|
|
|
|
/* special cases for NT status codes which cannot be translated to DOS codes */
|
|
if (smb->Flags2 & SMBFLG2_ERR_STATUS) {
|
|
__u32 err = le32_to_cpu(smb->Status.CifsError);
|
|
if (err == (NT_STATUS_NOT_A_REPARSE_POINT))
|
|
rc = -ENODATA;
|
|
else if (err == (NT_STATUS_PRIVILEGE_NOT_HELD))
|
|
rc = -EPERM;
|
|
}
|
|
|
|
cifs_dbg(FYI, "Mapping smb error code 0x%x to POSIX err %d\n",
|
|
le32_to_cpu(smb->Status.CifsError), rc);
|
|
|
|
/* generic corrective action e.g. reconnect SMB session on
|
|
* ERRbaduid could be added */
|
|
|
|
if (rc == -EIO)
|
|
smb_EIO2(smb_eio_trace_smb1_received_error,
|
|
le32_to_cpu(smb->Status.CifsError),
|
|
le16_to_cpu(smb->Flags2));
|
|
return rc;
|
|
}
|
|
|
|
int
|
|
map_and_check_smb_error(struct TCP_Server_Info *server,
|
|
struct mid_q_entry *mid, bool logErr)
|
|
{
|
|
int rc;
|
|
struct smb_hdr *smb = (struct smb_hdr *)mid->resp_buf;
|
|
|
|
rc = map_smb_to_linux_error((char *)smb, logErr);
|
|
if (rc == -EACCES && !(smb->Flags2 & SMBFLG2_ERR_STATUS)) {
|
|
/* possible ERRBaduid */
|
|
__u8 class = smb->Status.DosError.ErrorClass;
|
|
__u16 code = le16_to_cpu(smb->Status.DosError.Error);
|
|
|
|
/* switch can be used to handle different errors */
|
|
if (class == ERRSRV && code == ERRbaduid) {
|
|
cifs_dbg(FYI, "Server returned 0x%x, reconnecting session...\n",
|
|
code);
|
|
cifs_signal_cifsd_for_reconnect(server, false);
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
#define DEFINE_CHECK_SORT_FUNC(__array, __field) \
|
|
static int __init __array ## _is_sorted(void) \
|
|
{ \
|
|
unsigned int i; \
|
|
\
|
|
/* Check whether the array is sorted in ascending order */ \
|
|
for (i = 1; i < ARRAY_SIZE(__array); i++) { \
|
|
if (__array[i].__field >= \
|
|
__array[i - 1].__field) \
|
|
continue; \
|
|
\
|
|
pr_err(#__array " array order is incorrect\n"); \
|
|
return -EINVAL; \
|
|
} \
|
|
\
|
|
return 0; \
|
|
}
|
|
|
|
/* ntstatus_to_dos_map_is_sorted */
|
|
DEFINE_CHECK_SORT_FUNC(ntstatus_to_dos_map, ntstatus);
|
|
/* mapping_table_ERRDOS_is_sorted */
|
|
DEFINE_CHECK_SORT_FUNC(mapping_table_ERRDOS, smb_err);
|
|
/* mapping_table_ERRSRV_is_sorted */
|
|
DEFINE_CHECK_SORT_FUNC(mapping_table_ERRSRV, smb_err);
|
|
|
|
int __init smb1_init_maperror(void)
|
|
{
|
|
int rc;
|
|
|
|
rc = ntstatus_to_dos_map_is_sorted();
|
|
if (rc)
|
|
return rc;
|
|
|
|
rc = mapping_table_ERRDOS_is_sorted();
|
|
if (rc)
|
|
return rc;
|
|
|
|
rc = mapping_table_ERRSRV_is_sorted();
|
|
if (rc)
|
|
return rc;
|
|
|
|
return rc;
|
|
}
|
|
|
|
#if IS_ENABLED(CONFIG_SMB1_KUNIT_TESTS)
|
|
const struct ntstatus_to_dos_err *
|
|
search_ntstatus_to_dos_map_test(__u32 ntstatus)
|
|
{
|
|
return search_ntstatus_to_dos_map(ntstatus);
|
|
}
|
|
EXPORT_SYMBOL_IF_KUNIT(search_ntstatus_to_dos_map_test);
|
|
|
|
const struct ntstatus_to_dos_err *
|
|
ntstatus_to_dos_map_test = ntstatus_to_dos_map;
|
|
EXPORT_SYMBOL_IF_KUNIT(ntstatus_to_dos_map_test);
|
|
|
|
unsigned int ntstatus_to_dos_num = ARRAY_SIZE(ntstatus_to_dos_map);
|
|
EXPORT_SYMBOL_IF_KUNIT(ntstatus_to_dos_num);
|
|
|
|
const struct smb_to_posix_error *
|
|
search_mapping_table_ERRDOS_test(__u16 smb_err)
|
|
{
|
|
return search_mapping_table_ERRDOS(smb_err);
|
|
}
|
|
EXPORT_SYMBOL_IF_KUNIT(search_mapping_table_ERRDOS_test);
|
|
|
|
const struct smb_to_posix_error *
|
|
mapping_table_ERRDOS_test = mapping_table_ERRDOS;
|
|
EXPORT_SYMBOL_IF_KUNIT(mapping_table_ERRDOS_test);
|
|
|
|
unsigned int mapping_table_ERRDOS_num = ARRAY_SIZE(mapping_table_ERRDOS);
|
|
EXPORT_SYMBOL_IF_KUNIT(mapping_table_ERRDOS_num);
|
|
|
|
const struct smb_to_posix_error *
|
|
search_mapping_table_ERRSRV_test(__u16 smb_err)
|
|
{
|
|
return search_mapping_table_ERRSRV(smb_err);
|
|
}
|
|
EXPORT_SYMBOL_IF_KUNIT(search_mapping_table_ERRSRV_test);
|
|
|
|
const struct smb_to_posix_error *
|
|
mapping_table_ERRSRV_test = mapping_table_ERRSRV;
|
|
EXPORT_SYMBOL_IF_KUNIT(mapping_table_ERRSRV_test);
|
|
|
|
unsigned int mapping_table_ERRSRV_num = ARRAY_SIZE(mapping_table_ERRSRV);
|
|
EXPORT_SYMBOL_IF_KUNIT(mapping_table_ERRSRV_num);
|
|
#endif
|