Merge branch 'android-4.9' into amlogic-4.9-dev

This commit is contained in:
Victor Wan
2017-05-18 14:52:37 +08:00
34 changed files with 422 additions and 161 deletions

View File

@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 9
SUBLEVEL = 26
SUBLEVEL = 27
EXTRAVERSION =
NAME = Roaring Lionus

View File

@@ -489,8 +489,7 @@ static int tpm_startup(struct tpm_chip *chip, __be16 startup_type)
int tpm_get_timeouts(struct tpm_chip *chip)
{
struct tpm_cmd_t tpm_cmd;
unsigned long new_timeout[4];
unsigned long old_timeout[4];
unsigned long timeout_old[4], timeout_chip[4], timeout_eff[4];
struct duration_t *duration_cap;
ssize_t rc;
@@ -542,11 +541,15 @@ int tpm_get_timeouts(struct tpm_chip *chip)
!= sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
return -EINVAL;
old_timeout[0] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.a);
old_timeout[1] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.b);
old_timeout[2] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.c);
old_timeout[3] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.d);
memcpy(new_timeout, old_timeout, sizeof(new_timeout));
timeout_old[0] = jiffies_to_usecs(chip->timeout_a);
timeout_old[1] = jiffies_to_usecs(chip->timeout_b);
timeout_old[2] = jiffies_to_usecs(chip->timeout_c);
timeout_old[3] = jiffies_to_usecs(chip->timeout_d);
timeout_chip[0] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.a);
timeout_chip[1] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.b);
timeout_chip[2] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.c);
timeout_chip[3] = be32_to_cpu(tpm_cmd.params.getcap_out.cap.timeout.d);
memcpy(timeout_eff, timeout_chip, sizeof(timeout_eff));
/*
* Provide ability for vendor overrides of timeout values in case
@@ -554,16 +557,24 @@ int tpm_get_timeouts(struct tpm_chip *chip)
*/
if (chip->ops->update_timeouts != NULL)
chip->timeout_adjusted =
chip->ops->update_timeouts(chip, new_timeout);
chip->ops->update_timeouts(chip, timeout_eff);
if (!chip->timeout_adjusted) {
/* Don't overwrite default if value is 0 */
if (new_timeout[0] != 0 && new_timeout[0] < 1000) {
int i;
/* Restore default if chip reported 0 */
int i;
for (i = 0; i < ARRAY_SIZE(timeout_eff); i++) {
if (timeout_eff[i])
continue;
timeout_eff[i] = timeout_old[i];
chip->timeout_adjusted = true;
}
if (timeout_eff[0] != 0 && timeout_eff[0] < 1000) {
/* timeouts in msec rather usec */
for (i = 0; i != ARRAY_SIZE(new_timeout); i++)
new_timeout[i] *= 1000;
for (i = 0; i != ARRAY_SIZE(timeout_eff); i++)
timeout_eff[i] *= 1000;
chip->timeout_adjusted = true;
}
}
@@ -572,16 +583,16 @@ int tpm_get_timeouts(struct tpm_chip *chip)
if (chip->timeout_adjusted) {
dev_info(&chip->dev,
HW_ERR "Adjusting reported timeouts: A %lu->%luus B %lu->%luus C %lu->%luus D %lu->%luus\n",
old_timeout[0], new_timeout[0],
old_timeout[1], new_timeout[1],
old_timeout[2], new_timeout[2],
old_timeout[3], new_timeout[3]);
timeout_chip[0], timeout_eff[0],
timeout_chip[1], timeout_eff[1],
timeout_chip[2], timeout_eff[2],
timeout_chip[3], timeout_eff[3]);
}
chip->timeout_a = usecs_to_jiffies(new_timeout[0]);
chip->timeout_b = usecs_to_jiffies(new_timeout[1]);
chip->timeout_c = usecs_to_jiffies(new_timeout[2]);
chip->timeout_d = usecs_to_jiffies(new_timeout[3]);
chip->timeout_a = usecs_to_jiffies(timeout_eff[0]);
chip->timeout_b = usecs_to_jiffies(timeout_eff[1]);
chip->timeout_c = usecs_to_jiffies(timeout_eff[2]);
chip->timeout_d = usecs_to_jiffies(timeout_eff[3]);
duration:
tpm_cmd.header.in = tpm_getcap_header;

View File

@@ -3115,7 +3115,7 @@ static int __init sm_it87_init(void)
{
int sioaddr[2] = { REG_2E, REG_4E };
struct it87_sio_data sio_data;
unsigned short isa_address;
unsigned short isa_address[2];
bool found = false;
int i, err;
@@ -3125,15 +3125,29 @@ static int __init sm_it87_init(void)
for (i = 0; i < ARRAY_SIZE(sioaddr); i++) {
memset(&sio_data, 0, sizeof(struct it87_sio_data));
isa_address = 0;
err = it87_find(sioaddr[i], &isa_address, &sio_data);
if (err || isa_address == 0)
isa_address[i] = 0;
err = it87_find(sioaddr[i], &isa_address[i], &sio_data);
if (err || isa_address[i] == 0)
continue;
/*
* Don't register second chip if its ISA address matches
* the first chip's ISA address.
*/
if (i && isa_address[i] == isa_address[0])
break;
err = it87_device_add(i, isa_address, &sio_data);
err = it87_device_add(i, isa_address[i], &sio_data);
if (err)
goto exit_dev_unregister;
found = true;
/*
* IT8705F may respond on both SIO addresses.
* Stop probing after finding one.
*/
if (sio_data.type == it87)
break;
}
if (!found) {

View File

@@ -1847,7 +1847,7 @@ static int ctl_ioctl(uint command, struct dm_ioctl __user *user)
if (r)
goto out;
param->data_size = sizeof(*param);
param->data_size = offsetof(struct dm_ioctl, data);
r = fn(param, input_param_size);
if (unlikely(param->flags & DM_BUFFER_FULL_FLAG) &&

View File

@@ -400,8 +400,6 @@ MODULE_PARM_DESC(storvsc_vcpus_per_sub_channel, "Ratio of VCPUs to subchannels")
*/
static int storvsc_timeout = 180;
static int msft_blist_flags = BLIST_TRY_VPD_PAGES;
#if IS_ENABLED(CONFIG_SCSI_FC_ATTRS)
static struct scsi_transport_template *fc_transport_template;
#endif
@@ -1283,6 +1281,22 @@ static int storvsc_do_io(struct hv_device *device,
return ret;
}
static int storvsc_device_alloc(struct scsi_device *sdevice)
{
/*
* Set blist flag to permit the reading of the VPD pages even when
* the target may claim SPC-2 compliance. MSFT targets currently
* claim SPC-2 compliance while they implement post SPC-2 features.
* With this flag we can correctly handle WRITE_SAME_16 issues.
*
* Hypervisor reports SCSI_UNKNOWN type for DVD ROM device but
* still supports REPORT LUN.
*/
sdevice->sdev_bflags = BLIST_REPORTLUN2 | BLIST_TRY_VPD_PAGES;
return 0;
}
static int storvsc_device_configure(struct scsi_device *sdevice)
{
@@ -1297,14 +1311,6 @@ static int storvsc_device_configure(struct scsi_device *sdevice)
sdevice->no_write_same = 1;
/*
* Add blist flags to permit the reading of the VPD pages even when
* the target may claim SPC-2 compliance. MSFT targets currently
* claim SPC-2 compliance while they implement post SPC-2 features.
* With this patch we can correctly handle WRITE_SAME_16 issues.
*/
sdevice->sdev_bflags |= msft_blist_flags;
/*
* If the host is WIN8 or WIN8 R2, claim conformance to SPC-3
* if the device is a MSFT virtual device. If the host is
@@ -1569,6 +1575,7 @@ static struct scsi_host_template scsi_driver = {
.eh_host_reset_handler = storvsc_host_reset_handler,
.proc_name = "storvsc_host",
.eh_timed_out = storvsc_eh_timed_out,
.slave_alloc = storvsc_device_alloc,
.slave_configure = storvsc_device_configure,
.cmd_per_lun = 255,
.this_id = -1,

View File

@@ -5621,17 +5621,15 @@ static pci_ers_result_t serial8250_io_slot_reset(struct pci_dev *dev)
static void serial8250_io_resume(struct pci_dev *dev)
{
struct serial_private *priv = pci_get_drvdata(dev);
const struct pciserial_board *board;
struct serial_private *new;
if (!priv)
return;
board = priv->board;
kfree(priv);
priv = pciserial_init_ports(dev, board);
if (!IS_ERR(priv)) {
pci_set_drvdata(dev, priv);
new = pciserial_init_ports(dev, priv->board);
if (!IS_ERR(new)) {
pci_set_drvdata(dev, new);
kfree(priv);
}
}

View File

@@ -315,7 +315,32 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
struct page **pages;
pgoff_t next_index;
int nr_pages = 0;
int ret;
int got = 0;
int ret = 0;
if (!current->journal_info) {
/* caller of readpages does not hold buffer and read caps
* (fadvise, madvise and readahead cases) */
int want = CEPH_CAP_FILE_CACHE;
ret = ceph_try_get_caps(ci, CEPH_CAP_FILE_RD, want, &got);
if (ret < 0) {
dout("start_read %p, error getting cap\n", inode);
} else if (!(got & want)) {
dout("start_read %p, no cache cap\n", inode);
ret = 0;
}
if (ret <= 0) {
if (got)
ceph_put_cap_refs(ci, got);
while (!list_empty(page_list)) {
page = list_entry(page_list->prev,
struct page, lru);
list_del(&page->lru);
put_page(page);
}
return ret;
}
}
off = (u64) page_offset(page);
@@ -338,15 +363,18 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
CEPH_OSD_FLAG_READ, NULL,
ci->i_truncate_seq, ci->i_truncate_size,
false);
if (IS_ERR(req))
return PTR_ERR(req);
if (IS_ERR(req)) {
ret = PTR_ERR(req);
goto out;
}
/* build page vector */
nr_pages = calc_pages_for(0, len);
pages = kmalloc(sizeof(*pages) * nr_pages, GFP_KERNEL);
ret = -ENOMEM;
if (!pages)
goto out;
if (!pages) {
ret = -ENOMEM;
goto out_put;
}
for (i = 0; i < nr_pages; ++i) {
page = list_entry(page_list->prev, struct page, lru);
BUG_ON(PageLocked(page));
@@ -379,6 +407,12 @@ static int start_read(struct inode *inode, struct list_head *page_list, int max)
if (ret < 0)
goto out_pages;
ceph_osdc_put_request(req);
/* After adding locked pages to page cache, the inode holds cache cap.
* So we can drop our cap refs. */
if (got)
ceph_put_cap_refs(ci, got);
return nr_pages;
out_pages:
@@ -387,8 +421,11 @@ out_pages:
unlock_page(pages[i]);
}
ceph_put_page_vector(pages, nr_pages, false);
out:
out_put:
ceph_osdc_put_request(req);
out:
if (got)
ceph_put_cap_refs(ci, got);
return ret;
}
@@ -425,7 +462,6 @@ static int ceph_readpages(struct file *file, struct address_space *mapping,
rc = start_read(inode, page_list, max);
if (rc < 0)
goto out;
BUG_ON(rc == 0);
}
out:
ceph_fscache_readpages_cancel(inode, page_list);
@@ -1372,9 +1408,11 @@ static int ceph_filemap_fault(struct vm_area_struct *vma, struct vm_fault *vmf)
inode, off, (size_t)PAGE_SIZE, ceph_cap_string(got));
if ((got & (CEPH_CAP_FILE_CACHE | CEPH_CAP_FILE_LAZYIO)) ||
ci->i_inline_version == CEPH_INLINE_NONE)
ci->i_inline_version == CEPH_INLINE_NONE) {
current->journal_info = vma->vm_file;
ret = filemap_fault(vma, vmf);
else
current->journal_info = NULL;
} else
ret = -EAGAIN;
dout("filemap_fault %p %llu~%zd dropping cap refs on %s ret %d\n",

View File

@@ -2479,6 +2479,27 @@ static void check_max_size(struct inode *inode, loff_t endoff)
ceph_check_caps(ci, CHECK_CAPS_AUTHONLY, NULL);
}
int ceph_try_get_caps(struct ceph_inode_info *ci, int need, int want, int *got)
{
int ret, err = 0;
BUG_ON(need & ~CEPH_CAP_FILE_RD);
BUG_ON(want & ~(CEPH_CAP_FILE_CACHE|CEPH_CAP_FILE_LAZYIO));
ret = ceph_pool_perm_check(ci, need);
if (ret < 0)
return ret;
ret = try_get_cap_refs(ci, need, want, 0, true, got, &err);
if (ret) {
if (err == -EAGAIN) {
ret = 0;
} else if (err < 0) {
ret = err;
}
}
return ret;
}
/*
* Wait for caps, and take cap references. If we can't get a WR cap
* due to a small max_size, make sure we check_max_size (and possibly

View File

@@ -1249,8 +1249,9 @@ again:
dout("aio_read %p %llx.%llx %llu~%u got cap refs on %s\n",
inode, ceph_vinop(inode), iocb->ki_pos, (unsigned)len,
ceph_cap_string(got));
current->journal_info = filp;
ret = generic_file_read_iter(iocb, to);
current->journal_info = NULL;
}
dout("aio_read %p %llx.%llx dropping cap refs on %s = %d\n",
inode, ceph_vinop(inode), ceph_cap_string(got), (int)ret);

View File

@@ -905,6 +905,8 @@ extern int ceph_encode_dentry_release(void **p, struct dentry *dn,
extern int ceph_get_caps(struct ceph_inode_info *ci, int need, int want,
loff_t endoff, int *got, struct page **pinned_page);
extern int ceph_try_get_caps(struct ceph_inode_info *ci,
int need, int want, int *got);
/* for counting open files by mode */
extern void __ceph_get_fmode(struct ceph_inode_info *ci, int mode);

View File

@@ -241,6 +241,7 @@ struct smb_version_operations {
/* verify the message */
int (*check_message)(char *, unsigned int, struct TCP_Server_Info *);
bool (*is_oplock_break)(char *, struct TCP_Server_Info *);
int (*handle_cancelled_mid)(char *, struct TCP_Server_Info *);
void (*downgrade_oplock)(struct TCP_Server_Info *,
struct cifsInodeInfo *, bool);
/* process transaction2 response */
@@ -1314,12 +1315,19 @@ struct mid_q_entry {
void *callback_data; /* general purpose pointer for callback */
void *resp_buf; /* pointer to received SMB header */
int mid_state; /* wish this were enum but can not pass to wait_event */
unsigned int mid_flags;
__le16 command; /* smb command code */
bool large_buf:1; /* if valid response, is pointer to large buf */
bool multiRsp:1; /* multiple trans2 responses for one request */
bool multiEnd:1; /* both received */
};
struct close_cancelled_open {
struct cifs_fid fid;
struct cifs_tcon *tcon;
struct work_struct work;
};
/* Make code in transport.c a little cleaner by moving
update of optional stats into function below */
#ifdef CONFIG_CIFS_STATS2
@@ -1451,6 +1459,9 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
#define MID_RESPONSE_MALFORMED 0x10
#define MID_SHUTDOWN 0x20
/* Flags */
#define MID_WAIT_CANCELLED 1 /* Cancelled while waiting for response */
/* Types of response buffer returned from SendReceive2 */
#define CIFS_NO_BUFFER 0 /* Response buffer not returned */
#define CIFS_SMALL_BUFFER 1

View File

@@ -1423,6 +1423,8 @@ cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
length = discard_remaining_data(server);
dequeue_mid(mid, rdata->result);
mid->resp_buf = server->smallbuf;
server->smallbuf = NULL;
return length;
}
@@ -1534,6 +1536,8 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
return cifs_readv_discard(server, mid);
dequeue_mid(mid, false);
mid->resp_buf = server->smallbuf;
server->smallbuf = NULL;
return length;
}

View File

@@ -882,10 +882,19 @@ cifs_demultiplex_thread(void *p)
server->lstrp = jiffies;
if (mid_entry != NULL) {
if ((mid_entry->mid_flags & MID_WAIT_CANCELLED) &&
mid_entry->mid_state == MID_RESPONSE_RECEIVED &&
server->ops->handle_cancelled_mid)
server->ops->handle_cancelled_mid(
mid_entry->resp_buf,
server);
if (!mid_entry->multiRsp || mid_entry->multiEnd)
mid_entry->callback(mid_entry);
} else if (!server->ops->is_oplock_break ||
!server->ops->is_oplock_break(buf, server)) {
} else if (server->ops->is_oplock_break &&
server->ops->is_oplock_break(buf, server)) {
cifs_dbg(FYI, "Received oplock break\n");
} else {
cifs_dbg(VFS, "No task to wake, unknown frame received! NumMids %d\n",
atomic_read(&midCount));
cifs_dump_mem("Received Data is: ", buf,

View File

@@ -654,3 +654,47 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
cifs_dbg(FYI, "Can not process oplock break for non-existent connection\n");
return false;
}
void
smb2_cancelled_close_fid(struct work_struct *work)
{
struct close_cancelled_open *cancelled = container_of(work,
struct close_cancelled_open, work);
cifs_dbg(VFS, "Close unmatched open\n");
SMB2_close(0, cancelled->tcon, cancelled->fid.persistent_fid,
cancelled->fid.volatile_fid);
cifs_put_tcon(cancelled->tcon);
kfree(cancelled);
}
int
smb2_handle_cancelled_mid(char *buffer, struct TCP_Server_Info *server)
{
struct smb2_hdr *hdr = (struct smb2_hdr *)buffer;
struct smb2_create_rsp *rsp = (struct smb2_create_rsp *)buffer;
struct cifs_tcon *tcon;
struct close_cancelled_open *cancelled;
if (hdr->Command != SMB2_CREATE || hdr->Status != STATUS_SUCCESS)
return 0;
cancelled = kzalloc(sizeof(*cancelled), GFP_KERNEL);
if (!cancelled)
return -ENOMEM;
tcon = smb2_find_smb_tcon(server, hdr->SessionId, hdr->TreeId);
if (!tcon) {
kfree(cancelled);
return -ENOENT;
}
cancelled->fid.persistent_fid = rsp->PersistentFileId;
cancelled->fid.volatile_fid = rsp->VolatileFileId;
cancelled->tcon = tcon;
INIT_WORK(&cancelled->work, smb2_cancelled_close_fid);
queue_work(cifsiod_wq, &cancelled->work);
return 0;
}

View File

@@ -1565,6 +1565,7 @@ struct smb_version_operations smb20_operations = {
.clear_stats = smb2_clear_stats,
.print_stats = smb2_print_stats,
.is_oplock_break = smb2_is_valid_oplock_break,
.handle_cancelled_mid = smb2_handle_cancelled_mid,
.downgrade_oplock = smb2_downgrade_oplock,
.need_neg = smb2_need_neg,
.negotiate = smb2_negotiate,
@@ -1645,6 +1646,7 @@ struct smb_version_operations smb21_operations = {
.clear_stats = smb2_clear_stats,
.print_stats = smb2_print_stats,
.is_oplock_break = smb2_is_valid_oplock_break,
.handle_cancelled_mid = smb2_handle_cancelled_mid,
.downgrade_oplock = smb2_downgrade_oplock,
.need_neg = smb2_need_neg,
.negotiate = smb2_negotiate,
@@ -1727,6 +1729,7 @@ struct smb_version_operations smb30_operations = {
.print_stats = smb2_print_stats,
.dump_share_caps = smb2_dump_share_caps,
.is_oplock_break = smb2_is_valid_oplock_break,
.handle_cancelled_mid = smb2_handle_cancelled_mid,
.downgrade_oplock = smb2_downgrade_oplock,
.need_neg = smb2_need_neg,
.negotiate = smb2_negotiate,
@@ -1815,6 +1818,7 @@ struct smb_version_operations smb311_operations = {
.print_stats = smb2_print_stats,
.dump_share_caps = smb2_dump_share_caps,
.is_oplock_break = smb2_is_valid_oplock_break,
.handle_cancelled_mid = smb2_handle_cancelled_mid,
.downgrade_oplock = smb2_downgrade_oplock,
.need_neg = smb2_need_neg,
.negotiate = smb2_negotiate,

View File

@@ -48,6 +48,10 @@ extern struct mid_q_entry *smb2_setup_request(struct cifs_ses *ses,
struct smb_rqst *rqst);
extern struct mid_q_entry *smb2_setup_async_request(
struct TCP_Server_Info *server, struct smb_rqst *rqst);
extern struct cifs_ses *smb2_find_smb_ses(struct TCP_Server_Info *server,
__u64 ses_id);
extern struct cifs_tcon *smb2_find_smb_tcon(struct TCP_Server_Info *server,
__u64 ses_id, __u32 tid);
extern int smb2_calc_signature(struct smb_rqst *rqst,
struct TCP_Server_Info *server);
extern int smb3_calc_signature(struct smb_rqst *rqst,
@@ -158,6 +162,9 @@ extern int SMB2_set_compression(const unsigned int xid, struct cifs_tcon *tcon,
extern int SMB2_oplock_break(const unsigned int xid, struct cifs_tcon *tcon,
const u64 persistent_fid, const u64 volatile_fid,
const __u8 oplock_level);
extern int smb2_handle_cancelled_mid(char *buffer,
struct TCP_Server_Info *server);
void smb2_cancelled_close_fid(struct work_struct *work);
extern int SMB2_QFS_info(const unsigned int xid, struct cifs_tcon *tcon,
u64 persistent_file_id, u64 volatile_file_id,
struct kstatfs *FSData);

View File

@@ -115,22 +115,68 @@ smb3_crypto_shash_allocate(struct TCP_Server_Info *server)
}
static struct cifs_ses *
smb2_find_smb_ses(struct smb2_hdr *smb2hdr, struct TCP_Server_Info *server)
smb2_find_smb_ses_unlocked(struct TCP_Server_Info *server, __u64 ses_id)
{
struct cifs_ses *ses;
spin_lock(&cifs_tcp_ses_lock);
list_for_each_entry(ses, &server->smb_ses_list, smb_ses_list) {
if (ses->Suid != smb2hdr->SessionId)
if (ses->Suid != ses_id)
continue;
spin_unlock(&cifs_tcp_ses_lock);
return ses;
}
spin_unlock(&cifs_tcp_ses_lock);
return NULL;
}
struct cifs_ses *
smb2_find_smb_ses(struct TCP_Server_Info *server, __u64 ses_id)
{
struct cifs_ses *ses;
spin_lock(&cifs_tcp_ses_lock);
ses = smb2_find_smb_ses_unlocked(server, ses_id);
spin_unlock(&cifs_tcp_ses_lock);
return ses;
}
static struct cifs_tcon *
smb2_find_smb_sess_tcon_unlocked(struct cifs_ses *ses, __u32 tid)
{
struct cifs_tcon *tcon;
list_for_each_entry(tcon, &ses->tcon_list, tcon_list) {
if (tcon->tid != tid)
continue;
++tcon->tc_count;
return tcon;
}
return NULL;
}
/*
* Obtain tcon corresponding to the tid in the given
* cifs_ses
*/
struct cifs_tcon *
smb2_find_smb_tcon(struct TCP_Server_Info *server, __u64 ses_id, __u32 tid)
{
struct cifs_ses *ses;
struct cifs_tcon *tcon;
spin_lock(&cifs_tcp_ses_lock);
ses = smb2_find_smb_ses_unlocked(server, ses_id);
if (!ses) {
spin_unlock(&cifs_tcp_ses_lock);
return NULL;
}
tcon = smb2_find_smb_sess_tcon_unlocked(ses, tid);
spin_unlock(&cifs_tcp_ses_lock);
return tcon;
}
int
smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
@@ -142,7 +188,7 @@ smb2_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
struct cifs_ses *ses;
ses = smb2_find_smb_ses(smb2_pdu, server);
ses = smb2_find_smb_ses(server, smb2_pdu->SessionId);
if (!ses) {
cifs_dbg(VFS, "%s: Could not find session\n", __func__);
return 0;
@@ -359,7 +405,7 @@ smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
struct smb2_hdr *smb2_pdu = (struct smb2_hdr *)iov[0].iov_base;
struct cifs_ses *ses;
ses = smb2_find_smb_ses(smb2_pdu, server);
ses = smb2_find_smb_ses(server, smb2_pdu->SessionId);
if (!ses) {
cifs_dbg(VFS, "%s: Could not find session\n", __func__);
return 0;

View File

@@ -727,9 +727,11 @@ SendReceive2(const unsigned int xid, struct cifs_ses *ses,
rc = wait_for_response(ses->server, midQ);
if (rc != 0) {
cifs_dbg(FYI, "Cancelling wait for mid %llu\n", midQ->mid);
send_cancel(ses->server, buf, midQ);
spin_lock(&GlobalMid_Lock);
if (midQ->mid_state == MID_REQUEST_SUBMITTED) {
midQ->mid_flags |= MID_WAIT_CANCELLED;
midQ->callback = DeleteMidQEntry;
spin_unlock(&GlobalMid_Lock);
cifs_small_buf_release(buf);

View File

@@ -60,6 +60,14 @@ static int sdcardfs_d_revalidate(struct dentry *dentry, unsigned int flags)
lower_dentry = lower_path.dentry;
lower_cur_parent_dentry = dget_parent(lower_dentry);
if ((lower_dentry->d_flags & DCACHE_OP_REVALIDATE)) {
err = lower_dentry->d_op->d_revalidate(lower_dentry, flags);
if (err == 0) {
d_drop(dentry);
goto out;
}
}
spin_lock(&lower_dentry->d_lock);
if (d_unhashed(lower_dentry)) {
spin_unlock(&lower_dentry->d_lock);

View File

@@ -215,16 +215,16 @@ void fixup_lower_ownership(struct dentry *dentry, const char *name)
gid = AID_MEDIA_OBB;
break;
case PERM_ANDROID_PACKAGE:
if (info->d_uid != 0)
if (uid_is_app(info->d_uid))
gid = multiuser_get_ext_gid(info->d_uid);
else
gid = multiuser_get_uid(info->userid, uid);
gid = multiuser_get_uid(info->userid, AID_MEDIA_RW);
break;
case PERM_ANDROID_PACKAGE_CACHE:
if (info->d_uid != 0)
if (uid_is_app(info->d_uid))
gid = multiuser_get_ext_cache_gid(info->d_uid);
else
gid = multiuser_get_uid(info->userid, uid);
gid = multiuser_get_uid(info->userid, AID_MEDIA_RW);
break;
case PERM_PRE_ROOT:
default:

View File

@@ -358,9 +358,12 @@ ssize_t sdcardfs_read_iter(struct kiocb *iocb, struct iov_iter *iter)
get_file(lower_file); /* prevent lower_file from being released */
iocb->ki_filp = lower_file;
err = lower_file->f_op->read_iter(iocb, iter);
/* ? wait IO finish to update atime as ecryptfs ? */
iocb->ki_filp = file;
fput(lower_file);
/* update upper inode atime as needed */
if (err >= 0 || err == -EIOCBQUEUED)
fsstack_copy_attr_atime(file->f_path.dentry->d_inode,
file_inode(lower_file));
out:
return err;
}
@@ -384,6 +387,13 @@ ssize_t sdcardfs_write_iter(struct kiocb *iocb, struct iov_iter *iter)
err = lower_file->f_op->write_iter(iocb, iter);
iocb->ki_filp = file;
fput(lower_file);
/* update upper inode times/sizes as needed */
if (err >= 0 || err == -EIOCBQUEUED) {
fsstack_copy_inode_size(file->f_path.dentry->d_inode,
file_inode(lower_file));
fsstack_copy_attr_times(file->f_path.dentry->d_inode,
file_inode(lower_file));
}
out:
return err;
}

View File

@@ -622,11 +622,8 @@ static int sdcardfs_permission(struct vfsmount *mnt, struct inode *inode, int ma
struct inode tmp;
struct inode *top = grab_top(SDCARDFS_I(inode));
if (!top) {
release_top(SDCARDFS_I(inode));
WARN(1, "Top value was null!\n");
if (!top)
return -EINVAL;
}
/*
* Permission check on sdcardfs inode.
@@ -701,10 +698,8 @@ static int sdcardfs_setattr(struct vfsmount *mnt, struct dentry *dentry, struct
inode = d_inode(dentry);
top = grab_top(SDCARDFS_I(inode));
if (!top) {
release_top(SDCARDFS_I(inode));
if (!top)
return -EINVAL;
}
/*
* Permission check on sdcardfs inode.

View File

@@ -366,19 +366,22 @@ put_name:
/* instatiate a new negative dentry */
dname.name = name->name;
dname.len = name->len;
dname.hash = full_name_hash(lower_dir_dentry, dname.name, dname.len);
lower_dentry = d_lookup(lower_dir_dentry, &dname);
if (lower_dentry)
goto setup_lower;
lower_dentry = d_alloc(lower_dir_dentry, &dname);
/* See if the low-level filesystem might want
* to use its own hash
*/
lower_dentry = d_hash_and_lookup(lower_dir_dentry, &dname);
if (IS_ERR(lower_dentry))
return lower_dentry;
if (!lower_dentry) {
err = -ENOMEM;
/* We called vfs_path_lookup earlier, and did not get a negative
* dentry then. Don't confuse the lower filesystem by forcing
* one on it now...
*/
err = -ENOENT;
goto out;
}
d_add(lower_dentry, NULL); /* instantiate and hash */
setup_lower:
lower_path.dentry = lower_dentry;
lower_path.mnt = mntget(lower_dir_mnt);
sdcardfs_set_lower_path(dentry, &lower_path);

View File

@@ -35,6 +35,13 @@ static inline uid_t multiuser_get_uid(userid_t user_id, appid_t app_id)
return (user_id * AID_USER_OFFSET) + (app_id % AID_USER_OFFSET);
}
static inline bool uid_is_app(uid_t uid)
{
appid_t appid = uid % AID_USER_OFFSET;
return appid >= AID_APP_START && appid <= AID_APP_END;
}
static inline gid_t multiuser_get_ext_cache_gid(uid_t uid)
{
return uid - AID_APP_START + AID_EXT_CACHE_GID_START;

View File

@@ -192,9 +192,16 @@ static struct inode *sdcardfs_alloc_inode(struct super_block *sb)
return &i->vfs_inode;
}
static void i_callback(struct rcu_head *head)
{
struct inode *inode = container_of(head, struct inode, i_rcu);
kmem_cache_free(sdcardfs_inode_cachep, SDCARDFS_I(inode));
}
static void sdcardfs_destroy_inode(struct inode *inode)
{
kmem_cache_free(sdcardfs_inode_cachep, SDCARDFS_I(inode));
call_rcu(&inode->i_rcu, i_callback);
}
/* sdcardfs inode cache constructor */

View File

@@ -40,6 +40,7 @@ struct timerfd_ctx {
short unsigned settime_flags; /* to show in fdinfo */
struct rcu_head rcu;
struct list_head clist;
spinlock_t cancel_lock;
bool might_cancel;
};
@@ -112,7 +113,7 @@ void timerfd_clock_was_set(void)
rcu_read_unlock();
}
static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
static void __timerfd_remove_cancel(struct timerfd_ctx *ctx)
{
if (ctx->might_cancel) {
ctx->might_cancel = false;
@@ -122,6 +123,13 @@ static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
}
}
static void timerfd_remove_cancel(struct timerfd_ctx *ctx)
{
spin_lock(&ctx->cancel_lock);
__timerfd_remove_cancel(ctx);
spin_unlock(&ctx->cancel_lock);
}
static bool timerfd_canceled(struct timerfd_ctx *ctx)
{
if (!ctx->might_cancel || ctx->moffs.tv64 != KTIME_MAX)
@@ -132,6 +140,7 @@ static bool timerfd_canceled(struct timerfd_ctx *ctx)
static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
{
spin_lock(&ctx->cancel_lock);
if ((ctx->clockid == CLOCK_REALTIME ||
ctx->clockid == CLOCK_REALTIME_ALARM) &&
(flags & TFD_TIMER_ABSTIME) && (flags & TFD_TIMER_CANCEL_ON_SET)) {
@@ -141,9 +150,10 @@ static void timerfd_setup_cancel(struct timerfd_ctx *ctx, int flags)
list_add_rcu(&ctx->clist, &cancel_list);
spin_unlock(&cancel_lock);
}
} else if (ctx->might_cancel) {
timerfd_remove_cancel(ctx);
} else {
__timerfd_remove_cancel(ctx);
}
spin_unlock(&ctx->cancel_lock);
}
static ktime_t timerfd_get_remaining(struct timerfd_ctx *ctx)
@@ -400,6 +410,7 @@ SYSCALL_DEFINE2(timerfd_create, int, clockid, int, flags)
return -ENOMEM;
init_waitqueue_head(&ctx->wqh);
spin_lock_init(&ctx->cancel_lock);
ctx->clockid = clockid;
if (isalarm(ctx))

View File

@@ -10,4 +10,5 @@
#define XT_QTAGUID_SOCKET XT_OWNER_SOCKET
#define xt_qtaguid_match_info xt_owner_match_info
int qtaguid_untag(struct socket *sock, bool kernel);
#endif /* _XT_QTAGUID_MATCH_H */

View File

@@ -29,7 +29,6 @@ CONFIG_HIGH_RES_TIMERS=y
CONFIG_IKCONFIG=y
CONFIG_IKCONFIG_PROC=y
CONFIG_INET6_AH=y
CONFIG_INET6_DIAG_DESTROY=y
CONFIG_INET6_ESP=y
CONFIG_INET6_IPCOMP=y
CONFIG_INET=y
@@ -72,7 +71,6 @@ CONFIG_MODVERSIONS=y
CONFIG_NET=y
CONFIG_NETDEVICES=y
CONFIG_NETFILTER=y
CONFIG_NETFILTER_TPROXY=y
CONFIG_NETFILTER_XT_MATCH_COMMENT=y
CONFIG_NETFILTER_XT_MATCH_CONNLIMIT=y
CONFIG_NETFILTER_XT_MATCH_CONNMARK=y
@@ -88,7 +86,6 @@ CONFIG_NETFILTER_XT_MATCH_PKTTYPE=y
CONFIG_NETFILTER_XT_MATCH_POLICY=y
CONFIG_NETFILTER_XT_MATCH_QTAGUID=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2=y
CONFIG_NETFILTER_XT_MATCH_QUOTA2_LOG=y
CONFIG_NETFILTER_XT_MATCH_QUOTA=y
CONFIG_NETFILTER_XT_MATCH_SOCKET=y
CONFIG_NETFILTER_XT_MATCH_STATE=y
@@ -173,5 +170,4 @@ CONFIG_USB_CONFIGFS_F_MTP=y
CONFIG_USB_CONFIGFS_F_PTP=y
CONFIG_USB_CONFIGFS_UEVENT=y
CONFIG_USB_GADGET=y
CONFIG_USB_OTG_WAKELOCK=y
CONFIG_XFRM_USER=y

View File

@@ -1448,14 +1448,12 @@ static void cpuhp_store_callbacks(enum cpuhp_state state,
/* (Un)Install the callbacks for further cpu hotplug operations */
struct cpuhp_step *sp;
mutex_lock(&cpuhp_state_mutex);
sp = cpuhp_get_step(state);
sp->startup.single = startup;
sp->teardown.single = teardown;
sp->name = name;
sp->multi_instance = multi_instance;
INIT_HLIST_HEAD(&sp->list);
mutex_unlock(&cpuhp_state_mutex);
}
static void *cpuhp_get_teardown_cb(enum cpuhp_state state)
@@ -1525,16 +1523,13 @@ static int cpuhp_reserve_state(enum cpuhp_state state)
{
enum cpuhp_state i;
mutex_lock(&cpuhp_state_mutex);
for (i = CPUHP_AP_ONLINE_DYN; i <= CPUHP_AP_ONLINE_DYN_END; i++) {
if (cpuhp_ap_states[i].name)
continue;
cpuhp_ap_states[i].name = "Reserved";
mutex_unlock(&cpuhp_state_mutex);
return i;
}
mutex_unlock(&cpuhp_state_mutex);
WARN(1, "No more dynamic states available for CPU hotplug\n");
return -ENOSPC;
}
@@ -1551,6 +1546,7 @@ int __cpuhp_state_add_instance(enum cpuhp_state state, struct hlist_node *node,
return -EINVAL;
get_online_cpus();
mutex_lock(&cpuhp_state_mutex);
if (!invoke || !sp->startup.multi)
goto add_node;
@@ -1575,11 +1571,10 @@ int __cpuhp_state_add_instance(enum cpuhp_state state, struct hlist_node *node,
}
add_node:
ret = 0;
mutex_lock(&cpuhp_state_mutex);
hlist_add_head(node, &sp->list);
mutex_unlock(&cpuhp_state_mutex);
err:
mutex_unlock(&cpuhp_state_mutex);
put_online_cpus();
return ret;
}
@@ -1608,6 +1603,7 @@ int __cpuhp_setup_state(enum cpuhp_state state,
return -EINVAL;
get_online_cpus();
mutex_lock(&cpuhp_state_mutex);
/* currently assignments for the ONLINE state are possible */
if (state == CPUHP_AP_ONLINE_DYN) {
@@ -1643,6 +1639,8 @@ int __cpuhp_setup_state(enum cpuhp_state state,
}
}
out:
mutex_unlock(&cpuhp_state_mutex);
put_online_cpus();
if (!ret && dyn_state)
return state;
@@ -1662,6 +1660,8 @@ int __cpuhp_state_remove_instance(enum cpuhp_state state,
return -EINVAL;
get_online_cpus();
mutex_lock(&cpuhp_state_mutex);
if (!invoke || !cpuhp_get_teardown_cb(state))
goto remove;
/*
@@ -1678,7 +1678,6 @@ int __cpuhp_state_remove_instance(enum cpuhp_state state,
}
remove:
mutex_lock(&cpuhp_state_mutex);
hlist_del(node);
mutex_unlock(&cpuhp_state_mutex);
put_online_cpus();
@@ -1703,6 +1702,7 @@ void __cpuhp_remove_state(enum cpuhp_state state, bool invoke)
BUG_ON(cpuhp_cb_check(state));
get_online_cpus();
mutex_lock(&cpuhp_state_mutex);
if (sp->multi_instance) {
WARN(!hlist_empty(&sp->list),
@@ -1728,6 +1728,7 @@ void __cpuhp_remove_state(enum cpuhp_state state, bool invoke)
}
remove:
cpuhp_store_callbacks(state, NULL, NULL, NULL, false);
mutex_unlock(&cpuhp_state_mutex);
put_online_cpus();
}
EXPORT_SYMBOL(__cpuhp_remove_state);

View File

@@ -89,6 +89,7 @@
#include <linux/netfilter_ipv4.h>
#include <linux/random.h>
#include <linux/slab.h>
#include <linux/netfilter/xt_qtaguid.h>
#include <asm/uaccess.h>
@@ -412,6 +413,9 @@ int inet_release(struct socket *sock)
if (sk) {
long timeout;
#ifdef CONFIG_NETFILTER_XT_MATCH_QTAGUID
qtaguid_untag(sock, true);
#endif
/* Applications forget to leave groups before exiting */
ip_mc_drop_socket(sk);

View File

@@ -321,7 +321,7 @@ static void sock_tag_tree_erase(struct rb_root *st_to_free_tree)
st_entry->tag,
get_uid_from_tag(st_entry->tag));
rb_erase(&st_entry->sock_node, st_to_free_tree);
sockfd_put(st_entry->socket);
sock_put(st_entry->sk);
kfree(st_entry);
}
}
@@ -1922,12 +1922,12 @@ static int qtaguid_ctrl_proc_show(struct seq_file *m, void *v)
{
struct sock_tag *sock_tag_entry = v;
uid_t uid;
long f_count;
CT_DEBUG("qtaguid: proc ctrl pid=%u tgid=%u uid=%u\n",
current->pid, current->tgid, from_kuid(&init_user_ns, current_fsuid()));
if (sock_tag_entry != SEQ_START_TOKEN) {
int sk_ref_count;
uid = get_uid_from_tag(sock_tag_entry->tag);
CT_DEBUG("qtaguid: proc_read(): sk=%p tag=0x%llx (uid=%u) "
"pid=%u\n",
@@ -1936,13 +1936,13 @@ static int qtaguid_ctrl_proc_show(struct seq_file *m, void *v)
uid,
sock_tag_entry->pid
);
f_count = atomic_long_read(
&sock_tag_entry->socket->file->f_count);
sk_ref_count = atomic_read(
&sock_tag_entry->sk->sk_refcnt);
seq_printf(m, "sock=%pK tag=0x%llx (uid=%u) pid=%u "
"f_count=%lu\n",
"f_count=%d\n",
sock_tag_entry->sk,
sock_tag_entry->tag, uid,
sock_tag_entry->pid, f_count);
sock_tag_entry->pid, sk_ref_count);
} else {
seq_printf(m, "events: sockets_tagged=%llu "
"sockets_untagged=%llu "
@@ -2238,8 +2238,8 @@ static int ctrl_cmd_tag(const char *input)
from_kuid(&init_user_ns, current_fsuid()));
goto err;
}
CT_DEBUG("qtaguid: ctrl_tag(%s): socket->...->f_count=%ld ->sk=%p\n",
input, atomic_long_read(&el_socket->file->f_count),
CT_DEBUG("qtaguid: ctrl_tag(%s): socket->...->sk_refcnt=%d ->sk=%p\n",
input, atomic_read(&el_socket->sk->sk_refcnt),
el_socket->sk);
if (argc < 3) {
acct_tag = make_atag_from_value(0);
@@ -2283,16 +2283,9 @@ static int ctrl_cmd_tag(const char *input)
struct tag_ref *prev_tag_ref_entry;
CT_DEBUG("qtaguid: ctrl_tag(%s): retag for sk=%p "
"st@%p ...->f_count=%ld\n",
"st@%p ...->sk_refcnt=%d\n",
input, el_socket->sk, sock_tag_entry,
atomic_long_read(&el_socket->file->f_count));
/*
* This is a re-tagging, so release the sock_fd that was
* locked at the time of the 1st tagging.
* There is still the ref from this call's sockfd_lookup() so
* it can be done within the spinlock.
*/
sockfd_put(sock_tag_entry->socket);
atomic_read(&el_socket->sk->sk_refcnt));
prev_tag_ref_entry = lookup_tag_ref(sock_tag_entry->tag,
&uid_tag_data_entry);
BUG_ON(IS_ERR_OR_NULL(prev_tag_ref_entry));
@@ -2312,8 +2305,12 @@ static int ctrl_cmd_tag(const char *input)
res = -ENOMEM;
goto err_tag_unref_put;
}
/*
* Hold the sk refcount here to make sure the sk pointer cannot
* be freed and reused
*/
sock_hold(el_socket->sk);
sock_tag_entry->sk = el_socket->sk;
sock_tag_entry->socket = el_socket;
sock_tag_entry->pid = current->tgid;
sock_tag_entry->tag = combine_atag_with_uid(acct_tag, uid_int);
spin_lock_bh(&uid_tag_data_tree_lock);
@@ -2340,10 +2337,11 @@ static int ctrl_cmd_tag(const char *input)
atomic64_inc(&qtu_events.sockets_tagged);
}
spin_unlock_bh(&sock_tag_list_lock);
/* We keep the ref to the socket (file) until it is untagged */
CT_DEBUG("qtaguid: ctrl_tag(%s): done st@%p ...->f_count=%ld\n",
/* We keep the ref to the sk until it is untagged */
CT_DEBUG("qtaguid: ctrl_tag(%s): done st@%p ...->sk_refcnt=%d\n",
input, sock_tag_entry,
atomic_long_read(&el_socket->file->f_count));
atomic_read(&el_socket->sk->sk_refcnt));
sockfd_put(el_socket);
return 0;
err_tag_unref_put:
@@ -2351,8 +2349,8 @@ err_tag_unref_put:
tag_ref_entry->num_sock_tags--;
free_tag_ref_from_utd_entry(tag_ref_entry, uid_tag_data_entry);
err_put:
CT_DEBUG("qtaguid: ctrl_tag(%s): done. ...->f_count=%ld\n",
input, atomic_long_read(&el_socket->file->f_count) - 1);
CT_DEBUG("qtaguid: ctrl_tag(%s): done. ...->sk_refcnt=%d\n",
input, atomic_read(&el_socket->sk->sk_refcnt) - 1);
/* Release the sock_fd that was grabbed by sockfd_lookup(). */
sockfd_put(el_socket);
return res;
@@ -2368,17 +2366,13 @@ static int ctrl_cmd_untag(const char *input)
int sock_fd = 0;
struct socket *el_socket;
int res, argc;
struct sock_tag *sock_tag_entry;
struct tag_ref *tag_ref_entry;
struct uid_tag_data *utd_entry;
struct proc_qtu_data *pqd_entry;
argc = sscanf(input, "%c %d", &cmd, &sock_fd);
CT_DEBUG("qtaguid: ctrl_untag(%s): argc=%d cmd=%c sock_fd=%d\n",
input, argc, cmd, sock_fd);
if (argc < 2) {
res = -EINVAL;
goto err;
return res;
}
el_socket = sockfd_lookup(sock_fd, &res); /* This locks the file */
if (!el_socket) {
@@ -2386,17 +2380,31 @@ static int ctrl_cmd_untag(const char *input)
" sock_fd=%d err=%d pid=%u tgid=%u uid=%u\n",
input, sock_fd, res, current->pid, current->tgid,
from_kuid(&init_user_ns, current_fsuid()));
goto err;
return res;
}
CT_DEBUG("qtaguid: ctrl_untag(%s): socket->...->f_count=%ld ->sk=%p\n",
input, atomic_long_read(&el_socket->file->f_count),
el_socket->sk);
res = qtaguid_untag(el_socket, false);
sockfd_put(el_socket);
return res;
}
int qtaguid_untag(struct socket *el_socket, bool kernel)
{
int res;
pid_t pid;
struct sock_tag *sock_tag_entry;
struct tag_ref *tag_ref_entry;
struct uid_tag_data *utd_entry;
struct proc_qtu_data *pqd_entry;
spin_lock_bh(&sock_tag_list_lock);
sock_tag_entry = get_sock_stat_nl(el_socket->sk);
if (!sock_tag_entry) {
spin_unlock_bh(&sock_tag_list_lock);
res = -EINVAL;
goto err_put;
return res;
}
/*
* The socket already belongs to the current process
@@ -2408,20 +2416,26 @@ static int ctrl_cmd_untag(const char *input)
BUG_ON(!tag_ref_entry);
BUG_ON(tag_ref_entry->num_sock_tags <= 0);
spin_lock_bh(&uid_tag_data_tree_lock);
if (kernel)
pid = sock_tag_entry->pid;
else
pid = current->tgid;
pqd_entry = proc_qtu_data_tree_search(
&proc_qtu_data_tree, current->tgid);
&proc_qtu_data_tree, pid);
/*
* TODO: remove if, and start failing.
* At first, we want to catch user-space code that is not
* opening the /dev/xt_qtaguid.
*/
if (IS_ERR_OR_NULL(pqd_entry))
if (IS_ERR_OR_NULL(pqd_entry) || !sock_tag_entry->list.next) {
pr_warn_once("qtaguid: %s(): "
"User space forgot to open /dev/xt_qtaguid? "
"pid=%u tgid=%u uid=%u\n", __func__,
current->pid, current->tgid, from_kuid(&init_user_ns, current_fsuid()));
else
"pid=%u tgid=%u sk_pid=%u, uid=%u\n", __func__,
current->pid, current->tgid, sock_tag_entry->pid,
from_kuid(&init_user_ns, current_fsuid()));
} else {
list_del(&sock_tag_entry->list);
}
spin_unlock_bh(&uid_tag_data_tree_lock);
/*
* We don't free tag_ref from the utd_entry here,
@@ -2430,30 +2444,17 @@ static int ctrl_cmd_untag(const char *input)
tag_ref_entry->num_sock_tags--;
spin_unlock_bh(&sock_tag_list_lock);
/*
* Release the sock_fd that was grabbed at tag time,
* and once more for the sockfd_lookup() here.
* Release the sock_fd that was grabbed at tag time.
*/
sockfd_put(sock_tag_entry->socket);
CT_DEBUG("qtaguid: ctrl_untag(%s): done. st@%p ...->f_count=%ld\n",
input, sock_tag_entry,
atomic_long_read(&el_socket->file->f_count) - 1);
sockfd_put(el_socket);
sock_put(sock_tag_entry->sk);
CT_DEBUG("qtaguid: done. st@%p ...->sk_refcnt=%d\n",
sock_tag_entry,
atomic_read(&el_socket->sk->sk_refcnt));
kfree(sock_tag_entry);
atomic64_inc(&qtu_events.sockets_untagged);
return 0;
err_put:
CT_DEBUG("qtaguid: ctrl_untag(%s): done. socket->...->f_count=%ld\n",
input, atomic_long_read(&el_socket->file->f_count) - 1);
/* Release the sock_fd that was grabbed by sockfd_lookup(). */
sockfd_put(el_socket);
return res;
err:
CT_DEBUG("qtaguid: ctrl_untag(%s): done.\n", input);
return res;
}
static ssize_t qtaguid_ctrl_parse(const char *input, size_t count)

View File

@@ -256,8 +256,6 @@ struct iface_stat_work {
struct sock_tag {
struct rb_node sock_node;
struct sock *sk; /* Only used as a number, never dereferenced */
/* The socket is needed for sockfd_put() */
struct socket *socket;
/* Used to associate with a given pid */
struct list_head list; /* in proc_qtu_data.sock_tag_list */
pid_t pid;

View File

@@ -24,7 +24,7 @@
#include <linux/rbtree.h>
#include <linux/slab.h>
#include <linux/spinlock_types.h>
#include <net/sock.h>
#include "xt_qtaguid_internal.h"
#include "xt_qtaguid_print.h"
@@ -237,10 +237,10 @@ char *pp_sock_tag(struct sock_tag *st)
tag_str = pp_tag_t(&st->tag);
res = kasprintf(GFP_ATOMIC, "sock_tag@%p{"
"sock_node=rb_node{...}, "
"sk=%p socket=%p (f_count=%lu), list=list_head{...}, "
"sk=%p (f_count=%d), list=list_head{...}, "
"pid=%u, tag=%s}",
st, st->sk, st->socket, atomic_long_read(
&st->socket->file->f_count),
st, st->sk, atomic_read(
&st->sk->sk_refcnt),
st->pid, tag_str);
_bug_on_err_or_null(res);
kfree(tag_str);

View File

@@ -241,7 +241,7 @@ static struct xfrm_algo_desc aalg_list[] = {
.uinfo = {
.auth = {
.icv_truncbits = 96,
.icv_truncbits = 128,
.icv_fullbits = 256,
}
},