Merge branch 'for-next' of git://git.samba.org/sfrench/cifs-2.6

Pull cifs fixes from Steve French:
 "This ncludes various cifs/smb3 bug fixes, mostly for stable as well.

  In the next week I expect that Germano will have some reconnection
  fixes, and also I expect to have the remaining pieces of the snapshot
  enablement and SMB3 ACLs, but wanted to get this set of bug fixes in"

* 'for-next' of git://git.samba.org/sfrench/cifs-2.6:
  cifs_get_root shouldn't use path with tree name
  Fix default behaviour for empty domains and add domainauto option
  cifs: use %16phN for formatting md5 sum
  cifs: Fix smbencrypt() to stop pointing a scatterlist at the stack
  CIFS: Fix a possible double locking of mutex during reconnect
  CIFS: Fix a possible memory corruption during reconnect
  CIFS: Fix a possible memory corruption in push locks
  CIFS: Fix missing nls unload in smb2_reconnect()
  CIFS: Decrease verbosity of ioctl call
  SMB3: parsing for new snapshot timestamp mount parm
This commit is contained in:
Linus Torvalds 2016-12-24 11:37:18 -08:00
commit 1dd5c6b153
14 changed files with 177 additions and 90 deletions

View File

@ -699,11 +699,15 @@ setup_ntlmv2_rsp(struct cifs_ses *ses, const struct nls_table *nls_cp)
if (ses->server->negflavor == CIFS_NEGFLAVOR_EXTENDED) {
if (!ses->domainName) {
rc = find_domain_name(ses, nls_cp);
if (rc) {
cifs_dbg(VFS, "error %d finding domain name\n",
rc);
goto setup_ntlmv2_rsp_ret;
if (ses->domainAuto) {
rc = find_domain_name(ses, nls_cp);
if (rc) {
cifs_dbg(VFS, "error %d finding domain name\n",
rc);
goto setup_ntlmv2_rsp_ret;
}
} else {
ses->domainName = kstrdup("", GFP_KERNEL);
}
}
} else {

View File

@ -615,7 +615,7 @@ cifs_get_root(struct smb_vol *vol, struct super_block *sb)
return dget(sb->s_root);
full_path = cifs_build_path_to_root(vol, cifs_sb,
cifs_sb_master_tcon(cifs_sb));
cifs_sb_master_tcon(cifs_sb), 0);
if (full_path == NULL)
return ERR_PTR(-ENOMEM);

View File

@ -514,6 +514,7 @@ struct smb_vol {
bool persistent:1;
bool nopersistent:1;
bool resilient:1; /* noresilient not required since not fored for CA */
bool domainauto:1;
unsigned int rsize;
unsigned int wsize;
bool sockopt_tcp_nodelay:1;
@ -525,6 +526,7 @@ struct smb_vol {
struct sockaddr_storage srcaddr; /* allow binding to a local IP */
struct nls_table *local_nls;
unsigned int echo_interval; /* echo interval in secs */
__u64 snapshot_time; /* needed for timewarp tokens */
unsigned int max_credits; /* smb3 max_credits 10 < credits < 60000 */
};
@ -646,6 +648,8 @@ struct TCP_Server_Info {
unsigned int max_read;
unsigned int max_write;
__u8 preauth_hash[512];
struct delayed_work reconnect; /* reconnect workqueue job */
struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
#endif /* CONFIG_CIFS_SMB2 */
unsigned long echo_interval;
};
@ -827,6 +831,7 @@ struct cifs_ses {
enum securityEnum sectype; /* what security flavor was specified? */
bool sign; /* is signing required? */
bool need_reconnect:1; /* connection reset, uid now invalid */
bool domainAuto:1;
#ifdef CONFIG_CIFS_SMB2
__u16 session_flags;
__u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
@ -849,6 +854,7 @@ cap_unix(struct cifs_ses *ses)
struct cifs_tcon {
struct list_head tcon_list;
int tc_count;
struct list_head rlist; /* reconnect list */
struct list_head openFileList;
spinlock_t open_file_lock; /* protects list above */
struct cifs_ses *ses; /* pointer to session associated with */
@ -922,6 +928,7 @@ struct cifs_tcon {
bool broken_posix_open; /* e.g. Samba server versions < 3.3.2, 3.2.9 */
bool broken_sparse_sup; /* if server or share does not support sparse */
bool need_reconnect:1; /* connection reset, tid now invalid */
bool need_reopen_files:1; /* need to reopen tcon file handles */
bool use_resilient:1; /* use resilient instead of durable handles */
bool use_persistent:1; /* use persistent instead of durable handles */
#ifdef CONFIG_CIFS_SMB2
@ -932,6 +939,7 @@ struct cifs_tcon {
__u32 maximal_access;
__u32 vol_serial_number;
__le64 vol_create_time;
__u64 snapshot_time; /* for timewarp tokens - timestamp of snapshot */
__u32 ss_flags; /* sector size flags */
__u32 perf_sector_size; /* best sector size for perf */
__u32 max_chunks;

View File

@ -63,7 +63,8 @@ extern void exit_cifs_spnego(void);
extern char *build_path_from_dentry(struct dentry *);
extern char *cifs_build_path_to_root(struct smb_vol *vol,
struct cifs_sb_info *cifs_sb,
struct cifs_tcon *tcon);
struct cifs_tcon *tcon,
int add_treename);
extern char *build_wildcard_path_from_dentry(struct dentry *direntry);
extern char *cifs_compose_mount_options(const char *sb_mountdata,
const char *fullpath, const struct dfs_info3_param *ref,
@ -206,6 +207,9 @@ extern void cifs_add_pending_open_locked(struct cifs_fid *fid,
struct tcon_link *tlink,
struct cifs_pending_open *open);
extern void cifs_del_pending_open(struct cifs_pending_open *open);
extern void cifs_put_tcp_session(struct TCP_Server_Info *server,
int from_reconnect);
extern void cifs_put_tcon(struct cifs_tcon *tcon);
#if IS_ENABLED(CONFIG_CIFS_DFS_UPCALL)
extern void cifs_dfs_release_automount_timer(void);

View File

@ -53,6 +53,9 @@
#include "nterr.h"
#include "rfc1002pdu.h"
#include "fscache.h"
#ifdef CONFIG_CIFS_SMB2
#include "smb2proto.h"
#endif
#define CIFS_PORT 445
#define RFC1001_PORT 139
@ -89,6 +92,7 @@ enum {
Opt_multiuser, Opt_sloppy, Opt_nosharesock,
Opt_persistent, Opt_nopersistent,
Opt_resilient, Opt_noresilient,
Opt_domainauto,
/* Mount options which take numeric value */
Opt_backupuid, Opt_backupgid, Opt_uid,
@ -96,6 +100,7 @@ enum {
Opt_dirmode, Opt_port,
Opt_rsize, Opt_wsize, Opt_actimeo,
Opt_echo_interval, Opt_max_credits,
Opt_snapshot,
/* Mount options which take string value */
Opt_user, Opt_pass, Opt_ip,
@ -177,6 +182,7 @@ static const match_table_t cifs_mount_option_tokens = {
{ Opt_nopersistent, "nopersistenthandles"},
{ Opt_resilient, "resilienthandles"},
{ Opt_noresilient, "noresilienthandles"},
{ Opt_domainauto, "domainauto"},
{ Opt_backupuid, "backupuid=%s" },
{ Opt_backupgid, "backupgid=%s" },
@ -192,6 +198,7 @@ static const match_table_t cifs_mount_option_tokens = {
{ Opt_actimeo, "actimeo=%s" },
{ Opt_echo_interval, "echo_interval=%s" },
{ Opt_max_credits, "max_credits=%s" },
{ Opt_snapshot, "snapshot=%s" },
{ Opt_blank_user, "user=" },
{ Opt_blank_user, "username=" },
@ -1500,6 +1507,9 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
case Opt_noresilient:
vol->resilient = false; /* already the default */
break;
case Opt_domainauto:
vol->domainauto = true;
break;
/* Numeric Values */
case Opt_backupuid:
@ -1602,6 +1612,14 @@ cifs_parse_mount_options(const char *mountdata, const char *devname,
}
vol->echo_interval = option;
break;
case Opt_snapshot:
if (get_option_ul(args, &option)) {
cifs_dbg(VFS, "%s: Invalid snapshot time\n",
__func__);
goto cifs_parse_mount_err;
}
vol->snapshot_time = option;
break;
case Opt_max_credits:
if (get_option_ul(args, &option) || (option < 20) ||
(option > 60000)) {
@ -2101,8 +2119,8 @@ cifs_find_tcp_session(struct smb_vol *vol)
return NULL;
}
static void
cifs_put_tcp_session(struct TCP_Server_Info *server)
void
cifs_put_tcp_session(struct TCP_Server_Info *server, int from_reconnect)
{
struct task_struct *task;
@ -2119,6 +2137,19 @@ cifs_put_tcp_session(struct TCP_Server_Info *server)
cancel_delayed_work_sync(&server->echo);
#ifdef CONFIG_CIFS_SMB2
if (from_reconnect)
/*
* Avoid deadlock here: reconnect work calls
* cifs_put_tcp_session() at its end. Need to be sure
* that reconnect work does nothing with server pointer after
* that step.
*/
cancel_delayed_work(&server->reconnect);
else
cancel_delayed_work_sync(&server->reconnect);
#endif
spin_lock(&GlobalMid_Lock);
server->tcpStatus = CifsExiting;
spin_unlock(&GlobalMid_Lock);
@ -2183,6 +2214,10 @@ cifs_get_tcp_session(struct smb_vol *volume_info)
INIT_LIST_HEAD(&tcp_ses->tcp_ses_list);
INIT_LIST_HEAD(&tcp_ses->smb_ses_list);
INIT_DELAYED_WORK(&tcp_ses->echo, cifs_echo_request);
#ifdef CONFIG_CIFS_SMB2
INIT_DELAYED_WORK(&tcp_ses->reconnect, smb2_reconnect_server);
mutex_init(&tcp_ses->reconnect_mutex);
#endif
memcpy(&tcp_ses->srcaddr, &volume_info->srcaddr,
sizeof(tcp_ses->srcaddr));
memcpy(&tcp_ses->dstaddr, &volume_info->dstaddr,
@ -2341,7 +2376,7 @@ cifs_put_smb_ses(struct cifs_ses *ses)
spin_unlock(&cifs_tcp_ses_lock);
sesInfoFree(ses);
cifs_put_tcp_session(server);
cifs_put_tcp_session(server, 0);
}
#ifdef CONFIG_KEYS
@ -2515,7 +2550,7 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
mutex_unlock(&ses->session_mutex);
/* existing SMB ses has a server reference already */
cifs_put_tcp_session(server);
cifs_put_tcp_session(server, 0);
free_xid(xid);
return ses;
}
@ -2549,6 +2584,8 @@ cifs_get_smb_ses(struct TCP_Server_Info *server, struct smb_vol *volume_info)
if (!ses->domainName)
goto get_ses_fail;
}
if (volume_info->domainauto)
ses->domainAuto = volume_info->domainauto;
ses->cred_uid = volume_info->cred_uid;
ses->linux_uid = volume_info->linux_uid;
@ -2587,7 +2624,7 @@ static int match_tcon(struct cifs_tcon *tcon, const char *unc)
}
static struct cifs_tcon *
cifs_find_tcon(struct cifs_ses *ses, const char *unc)
cifs_find_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
{
struct list_head *tmp;
struct cifs_tcon *tcon;
@ -2595,8 +2632,14 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
spin_lock(&cifs_tcp_ses_lock);
list_for_each(tmp, &ses->tcon_list) {
tcon = list_entry(tmp, struct cifs_tcon, tcon_list);
if (!match_tcon(tcon, unc))
if (!match_tcon(tcon, volume_info->UNC))
continue;
#ifdef CONFIG_CIFS_SMB2
if (tcon->snapshot_time != volume_info->snapshot_time)
continue;
#endif /* CONFIG_CIFS_SMB2 */
++tcon->tc_count;
spin_unlock(&cifs_tcp_ses_lock);
return tcon;
@ -2605,7 +2648,7 @@ cifs_find_tcon(struct cifs_ses *ses, const char *unc)
return NULL;
}
static void
void
cifs_put_tcon(struct cifs_tcon *tcon)
{
unsigned int xid;
@ -2637,7 +2680,7 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
int rc, xid;
struct cifs_tcon *tcon;
tcon = cifs_find_tcon(ses, volume_info->UNC);
tcon = cifs_find_tcon(ses, volume_info);
if (tcon) {
cifs_dbg(FYI, "Found match on UNC path\n");
/* existing tcon already has a reference */
@ -2658,6 +2701,22 @@ cifs_get_tcon(struct cifs_ses *ses, struct smb_vol *volume_info)
goto out_fail;
}
if (volume_info->snapshot_time) {
#ifdef CONFIG_CIFS_SMB2
if (ses->server->vals->protocol_id == 0) {
cifs_dbg(VFS,
"Use SMB2 or later for snapshot mount option\n");
rc = -EOPNOTSUPP;
goto out_fail;
} else
tcon->snapshot_time = volume_info->snapshot_time;
#else
cifs_dbg(VFS, "Snapshot mount option requires SMB2 support\n");
rc = -EOPNOTSUPP;
goto out_fail;
#endif /* CONFIG_CIFS_SMB2 */
}
tcon->ses = ses;
if (volume_info->password) {
tcon->password = kstrdup(volume_info->password, GFP_KERNEL);
@ -3707,7 +3766,8 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
/*
* cifs_build_path_to_root works only when we have a valid tcon
*/
full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon);
full_path = cifs_build_path_to_root(volume_info, cifs_sb, tcon,
tcon->Flags & SMB_SHARE_IS_IN_DFS);
if (full_path == NULL) {
rc = -ENOMEM;
goto mount_fail_check;
@ -3793,7 +3853,7 @@ cifs_mount(struct cifs_sb_info *cifs_sb, struct smb_vol *volume_info)
else if (ses)
cifs_put_smb_ses(ses);
else
cifs_put_tcp_session(server);
cifs_put_tcp_session(server, 0);
bdi_destroy(&cifs_sb->bdi);
}
@ -4104,7 +4164,7 @@ cifs_construct_tcon(struct cifs_sb_info *cifs_sb, kuid_t fsuid)
ses = cifs_get_smb_ses(master_tcon->ses->server, vol_info);
if (IS_ERR(ses)) {
tcon = (struct cifs_tcon *)ses;
cifs_put_tcp_session(master_tcon->ses->server);
cifs_put_tcp_session(master_tcon->ses->server, 0);
goto out;
}

View File

@ -47,7 +47,7 @@ renew_parental_timestamps(struct dentry *direntry)
char *
cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
struct cifs_tcon *tcon)
struct cifs_tcon *tcon, int add_treename)
{
int pplen = vol->prepath ? strlen(vol->prepath) + 1 : 0;
int dfsplen;
@ -59,7 +59,7 @@ cifs_build_path_to_root(struct smb_vol *vol, struct cifs_sb_info *cifs_sb,
return full_path;
}
if (tcon->Flags & SMB_SHARE_IS_IN_DFS)
if (add_treename)
dfsplen = strnlen(tcon->treeName, MAX_TREE_SIZE + 1);
else
dfsplen = 0;

View File

@ -777,6 +777,11 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
struct list_head *tmp1;
struct list_head tmp_list;
if (!tcon->use_persistent || !tcon->need_reopen_files)
return;
tcon->need_reopen_files = false;
cifs_dbg(FYI, "Reopen persistent handles");
INIT_LIST_HEAD(&tmp_list);
@ -793,7 +798,8 @@ cifs_reopen_persistent_handles(struct cifs_tcon *tcon)
list_for_each_safe(tmp, tmp1, &tmp_list) {
open_file = list_entry(tmp, struct cifsFileInfo, rlist);
cifs_reopen_file(open_file, false /* do not flush */);
if (cifs_reopen_file(open_file, false /* do not flush */))
tcon->need_reopen_files = true;
list_del_init(&open_file->rlist);
cifsFileInfo_put(open_file);
}

View File

@ -189,7 +189,7 @@ long cifs_ioctl(struct file *filep, unsigned int command, unsigned long arg)
xid = get_xid();
cifs_sb = CIFS_SB(inode->i_sb);
cifs_dbg(VFS, "cifs ioctl 0x%x\n", command);
cifs_dbg(FYI, "cifs ioctl 0x%x\n", command);
switch (command) {
case FS_IOC_GETFLAGS:
if (pSMBFile == NULL)

View File

@ -45,13 +45,8 @@
(CIFS_MF_SYMLINK_LINK_OFFSET + CIFS_MF_SYMLINK_LINK_MAXLEN)
#define CIFS_MF_SYMLINK_LEN_FORMAT "XSym\n%04u\n"
#define CIFS_MF_SYMLINK_MD5_FORMAT \
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n"
#define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) \
md5_hash[0], md5_hash[1], md5_hash[2], md5_hash[3], \
md5_hash[4], md5_hash[5], md5_hash[6], md5_hash[7], \
md5_hash[8], md5_hash[9], md5_hash[10], md5_hash[11],\
md5_hash[12], md5_hash[13], md5_hash[14], md5_hash[15]
#define CIFS_MF_SYMLINK_MD5_FORMAT "%16phN\n"
#define CIFS_MF_SYMLINK_MD5_ARGS(md5_hash) md5_hash
static int
symlink_hash(unsigned int link_len, const char *link_str, u8 *md5_hash)

View File

@ -260,7 +260,7 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
* and check it for zero before using.
*/
max_buf = tlink_tcon(cfile->tlink)->ses->server->maxBuf;
if (!max_buf) {
if (max_buf < sizeof(struct smb2_lock_element)) {
free_xid(xid);
return -EINVAL;
}

View File

@ -250,16 +250,19 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
}
cifs_mark_open_files_invalid(tcon);
if (tcon->use_persistent)
tcon->need_reopen_files = true;
rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nls_codepage);
mutex_unlock(&tcon->ses->session_mutex);
if (tcon->use_persistent)
cifs_reopen_persistent_handles(tcon);
cifs_dbg(FYI, "reconnect tcon rc = %d\n", rc);
if (rc)
goto out;
if (smb2_command != SMB2_INTERNAL_CMD)
queue_delayed_work(cifsiod_wq, &server->reconnect, 0);
atomic_inc(&tconInfoReconnectCount);
out:
/*
@ -280,7 +283,7 @@ smb2_reconnect(__le16 smb2_command, struct cifs_tcon *tcon)
case SMB2_CHANGE_NOTIFY:
case SMB2_QUERY_INFO:
case SMB2_SET_INFO:
return -EAGAIN;
rc = -EAGAIN;
}
unload_nls(nls_codepage);
return rc;
@ -1972,6 +1975,55 @@ smb2_echo_callback(struct mid_q_entry *mid)
add_credits(server, credits_received, CIFS_ECHO_OP);
}
void smb2_reconnect_server(struct work_struct *work)
{
struct TCP_Server_Info *server = container_of(work,
struct TCP_Server_Info, reconnect.work);
struct cifs_ses *ses;
struct cifs_tcon *tcon, *tcon2;
struct list_head tmp_list;
int tcon_exist = false;
/* Prevent simultaneous reconnects that can corrupt tcon->rlist list */
mutex_lock(&server->reconnect_mutex);
INIT_LIST_HEAD(&tmp_list);
cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n");
spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
if (tcon->need_reconnect || tcon->need_reopen_files) {
tcon->tc_count++;
list_add_tail(&tcon->rlist, &tmp_list);
tcon_exist = true;
}
}
}
/*
* Get the reference to server struct to be sure that the last call of
* cifs_put_tcon() in the loop below won't release the server pointer.
*/
if (tcon_exist)
server->srv_count++;
spin_unlock(&cifs_tcp_ses_lock);
list_for_each_entry_safe(tcon, tcon2, &tmp_list, rlist) {
if (!smb2_reconnect(SMB2_INTERNAL_CMD, tcon))
cifs_reopen_persistent_handles(tcon);
list_del_init(&tcon->rlist);
cifs_put_tcon(tcon);
}
cifs_dbg(FYI, "Reconnecting tcons finished\n");
mutex_unlock(&server->reconnect_mutex);
/* now we can safely release srv struct */
if (tcon_exist)
cifs_put_tcp_session(server, 1);
}
int
SMB2_echo(struct TCP_Server_Info *server)
{
@ -1984,32 +2036,11 @@ SMB2_echo(struct TCP_Server_Info *server)
cifs_dbg(FYI, "In echo request\n");
if (server->tcpStatus == CifsNeedNegotiate) {
struct list_head *tmp, *tmp2;
struct cifs_ses *ses;
struct cifs_tcon *tcon;
cifs_dbg(FYI, "Need negotiate, reconnecting tcons\n");
spin_lock(&cifs_tcp_ses_lock);
list_for_each(tmp, &server->smb_ses_list) {
ses = list_entry(tmp, struct cifs_ses, smb_ses_list);
list_for_each(tmp2, &ses->tcon_list) {
tcon = list_entry(tmp2, struct cifs_tcon,
tcon_list);
/* add check for persistent handle reconnect */
if (tcon && tcon->need_reconnect) {
spin_unlock(&cifs_tcp_ses_lock);
rc = smb2_reconnect(SMB2_ECHO, tcon);
spin_lock(&cifs_tcp_ses_lock);
}
}
}
spin_unlock(&cifs_tcp_ses_lock);
/* No need to send echo on newly established connections */
queue_delayed_work(cifsiod_wq, &server->reconnect, 0);
return rc;
}
/* if no session, renegotiate failed above */
if (server->tcpStatus == CifsNeedNegotiate)
return -EIO;
rc = small_smb2_init(SMB2_ECHO, NULL, (void **)&req);
if (rc)
return rc;

View File

@ -80,6 +80,8 @@
#define SMB2_SET_INFO cpu_to_le16(SMB2_SET_INFO_HE)
#define SMB2_OPLOCK_BREAK cpu_to_le16(SMB2_OPLOCK_BREAK_HE)
#define SMB2_INTERNAL_CMD cpu_to_le16(0xFFFF)
#define NUMBER_OF_SMB2_COMMANDS 0x0013
/* BB FIXME - analyze following length BB */

View File

@ -96,6 +96,7 @@ extern int smb2_open_file(const unsigned int xid,
extern int smb2_unlock_range(struct cifsFileInfo *cfile,
struct file_lock *flock, const unsigned int xid);
extern int smb2_push_mandatory_locks(struct cifsFileInfo *cfile);
extern void smb2_reconnect_server(struct work_struct *work);
/*
* SMB2 Worker functions - most of protocol specific implementation details

View File

@ -23,7 +23,7 @@
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <crypto/skcipher.h>
#include <linux/crypto.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/fs.h>
@ -69,46 +69,22 @@ str_to_key(unsigned char *str, unsigned char *key)
static int
smbhash(unsigned char *out, const unsigned char *in, unsigned char *key)
{
int rc;
unsigned char key2[8];
struct crypto_skcipher *tfm_des;
struct scatterlist sgin, sgout;
struct skcipher_request *req;
struct crypto_cipher *tfm_des;
str_to_key(key, key2);
tfm_des = crypto_alloc_skcipher("ecb(des)", 0, CRYPTO_ALG_ASYNC);
tfm_des = crypto_alloc_cipher("des", 0, 0);
if (IS_ERR(tfm_des)) {
rc = PTR_ERR(tfm_des);
cifs_dbg(VFS, "could not allocate des crypto API\n");
goto smbhash_err;
return PTR_ERR(tfm_des);
}
req = skcipher_request_alloc(tfm_des, GFP_KERNEL);
if (!req) {
rc = -ENOMEM;
cifs_dbg(VFS, "could not allocate des crypto API\n");
goto smbhash_free_skcipher;
}
crypto_cipher_setkey(tfm_des, key2, 8);
crypto_cipher_encrypt_one(tfm_des, out, in);
crypto_free_cipher(tfm_des);
crypto_skcipher_setkey(tfm_des, key2, 8);
sg_init_one(&sgin, in, 8);
sg_init_one(&sgout, out, 8);
skcipher_request_set_callback(req, 0, NULL, NULL);
skcipher_request_set_crypt(req, &sgin, &sgout, 8, NULL);
rc = crypto_skcipher_encrypt(req);
if (rc)
cifs_dbg(VFS, "could not encrypt crypt key rc: %d\n", rc);
skcipher_request_free(req);
smbhash_free_skcipher:
crypto_free_skcipher(tfm_des);
smbhash_err:
return rc;
return 0;
}
static int