Commit fcd98d40 authored by Harald Freudenberger's avatar Harald Freudenberger Committed by Vasily Gorbik

s390/zcrypt: fix card and queue total counter wrap

The internal statistic counters for the total number of
requests processed per card and per queue used integers. So they do
wrap after a rather huge amount of crypto requests processed. This
patch introduces uint64 counters which should hold much longer but
still may wrap. The sysfs attributes request_count for card and queue
also used only %ld and now display the counter value with %llu.

This is not a security relevant fix. The int overflow which happened
is not in any way exploitable as a security breach.
Signed-off-by: default avatarHarald Freudenberger <freude@linux.ibm.com>
Signed-off-by: default avatarVasily Gorbik <gor@linux.ibm.com>
parent aab73d27
...@@ -162,7 +162,7 @@ struct ap_card { ...@@ -162,7 +162,7 @@ struct ap_card {
unsigned int functions; /* AP device function bitfield. */ unsigned int functions; /* AP device function bitfield. */
int queue_depth; /* AP queue depth.*/ int queue_depth; /* AP queue depth.*/
int id; /* AP card number. */ int id; /* AP card number. */
atomic_t total_request_count; /* # requests ever for this AP device.*/ atomic64_t total_request_count; /* # requests ever for this AP device.*/
}; };
#define to_ap_card(x) container_of((x), struct ap_card, ap_dev.device) #define to_ap_card(x) container_of((x), struct ap_card, ap_dev.device)
...@@ -179,7 +179,7 @@ struct ap_queue { ...@@ -179,7 +179,7 @@ struct ap_queue {
enum ap_state state; /* State of the AP device. */ enum ap_state state; /* State of the AP device. */
int pendingq_count; /* # requests on pendingq list. */ int pendingq_count; /* # requests on pendingq list. */
int requestq_count; /* # requests on requestq list. */ int requestq_count; /* # requests on requestq list. */
int total_request_count; /* # requests ever for this AP device.*/ u64 total_request_count; /* # requests ever for this AP device.*/
int request_timeout; /* Request timeout in jiffies. */ int request_timeout; /* Request timeout in jiffies. */
struct timer_list timeout; /* Timer for request timeouts. */ struct timer_list timeout; /* Timer for request timeouts. */
struct list_head pendingq; /* List of message sent to AP queue. */ struct list_head pendingq; /* List of message sent to AP queue. */
......
...@@ -63,13 +63,13 @@ static ssize_t request_count_show(struct device *dev, ...@@ -63,13 +63,13 @@ static ssize_t request_count_show(struct device *dev,
char *buf) char *buf)
{ {
struct ap_card *ac = to_ap_card(dev); struct ap_card *ac = to_ap_card(dev);
unsigned int req_cnt; u64 req_cnt;
req_cnt = 0; req_cnt = 0;
spin_lock_bh(&ap_list_lock); spin_lock_bh(&ap_list_lock);
req_cnt = atomic_read(&ac->total_request_count); req_cnt = atomic64_read(&ac->total_request_count);
spin_unlock_bh(&ap_list_lock); spin_unlock_bh(&ap_list_lock);
return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt); return snprintf(buf, PAGE_SIZE, "%llu\n", req_cnt);
} }
static ssize_t request_count_store(struct device *dev, static ssize_t request_count_store(struct device *dev,
...@@ -83,7 +83,7 @@ static ssize_t request_count_store(struct device *dev, ...@@ -83,7 +83,7 @@ static ssize_t request_count_store(struct device *dev,
for_each_ap_queue(aq, ac) for_each_ap_queue(aq, ac)
aq->total_request_count = 0; aq->total_request_count = 0;
spin_unlock_bh(&ap_list_lock); spin_unlock_bh(&ap_list_lock);
atomic_set(&ac->total_request_count, 0); atomic64_set(&ac->total_request_count, 0);
return count; return count;
} }
......
...@@ -479,12 +479,12 @@ static ssize_t request_count_show(struct device *dev, ...@@ -479,12 +479,12 @@ static ssize_t request_count_show(struct device *dev,
char *buf) char *buf)
{ {
struct ap_queue *aq = to_ap_queue(dev); struct ap_queue *aq = to_ap_queue(dev);
unsigned int req_cnt; u64 req_cnt;
spin_lock_bh(&aq->lock); spin_lock_bh(&aq->lock);
req_cnt = aq->total_request_count; req_cnt = aq->total_request_count;
spin_unlock_bh(&aq->lock); spin_unlock_bh(&aq->lock);
return snprintf(buf, PAGE_SIZE, "%d\n", req_cnt); return snprintf(buf, PAGE_SIZE, "%llu\n", req_cnt);
} }
static ssize_t request_count_store(struct device *dev, static ssize_t request_count_store(struct device *dev,
...@@ -676,7 +676,7 @@ void ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg) ...@@ -676,7 +676,7 @@ void ap_queue_message(struct ap_queue *aq, struct ap_message *ap_msg)
list_add_tail(&ap_msg->list, &aq->requestq); list_add_tail(&ap_msg->list, &aq->requestq);
aq->requestq_count++; aq->requestq_count++;
aq->total_request_count++; aq->total_request_count++;
atomic_inc(&aq->card->total_request_count); atomic64_inc(&aq->card->total_request_count);
/* Send/receive as many request from the queue as possible. */ /* Send/receive as many request from the queue as possible. */
ap_wait(ap_sm_event_loop(aq, AP_EVENT_POLL)); ap_wait(ap_sm_event_loop(aq, AP_EVENT_POLL));
spin_unlock_bh(&aq->lock); spin_unlock_bh(&aq->lock);
......
...@@ -606,8 +606,8 @@ static inline bool zcrypt_card_compare(struct zcrypt_card *zc, ...@@ -606,8 +606,8 @@ static inline bool zcrypt_card_compare(struct zcrypt_card *zc,
weight += atomic_read(&zc->load); weight += atomic_read(&zc->load);
pref_weight += atomic_read(&pref_zc->load); pref_weight += atomic_read(&pref_zc->load);
if (weight == pref_weight) if (weight == pref_weight)
return atomic_read(&zc->card->total_request_count) > return atomic64_read(&zc->card->total_request_count) >
atomic_read(&pref_zc->card->total_request_count); atomic64_read(&pref_zc->card->total_request_count);
return weight > pref_weight; return weight > pref_weight;
} }
...@@ -1226,11 +1226,12 @@ static void zcrypt_qdepth_mask(char qdepth[], size_t max_adapters) ...@@ -1226,11 +1226,12 @@ static void zcrypt_qdepth_mask(char qdepth[], size_t max_adapters)
spin_unlock(&zcrypt_list_lock); spin_unlock(&zcrypt_list_lock);
} }
static void zcrypt_perdev_reqcnt(int reqcnt[], size_t max_adapters) static void zcrypt_perdev_reqcnt(u32 reqcnt[], size_t max_adapters)
{ {
struct zcrypt_card *zc; struct zcrypt_card *zc;
struct zcrypt_queue *zq; struct zcrypt_queue *zq;
int card; int card;
u64 cnt;
memset(reqcnt, 0, sizeof(int) * max_adapters); memset(reqcnt, 0, sizeof(int) * max_adapters);
spin_lock(&zcrypt_list_lock); spin_lock(&zcrypt_list_lock);
...@@ -1242,8 +1243,9 @@ static void zcrypt_perdev_reqcnt(int reqcnt[], size_t max_adapters) ...@@ -1242,8 +1243,9 @@ static void zcrypt_perdev_reqcnt(int reqcnt[], size_t max_adapters)
|| card >= max_adapters) || card >= max_adapters)
continue; continue;
spin_lock(&zq->queue->lock); spin_lock(&zq->queue->lock);
reqcnt[card] = zq->queue->total_request_count; cnt = zq->queue->total_request_count;
spin_unlock(&zq->queue->lock); spin_unlock(&zq->queue->lock);
reqcnt[card] = (cnt < UINT_MAX) ? (u32) cnt : UINT_MAX;
} }
} }
local_bh_enable(); local_bh_enable();
...@@ -1421,9 +1423,9 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, ...@@ -1421,9 +1423,9 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
return 0; return 0;
} }
case ZCRYPT_PERDEV_REQCNT: { case ZCRYPT_PERDEV_REQCNT: {
int *reqcnt; u32 *reqcnt;
reqcnt = kcalloc(AP_DEVICES, sizeof(int), GFP_KERNEL); reqcnt = kcalloc(AP_DEVICES, sizeof(u32), GFP_KERNEL);
if (!reqcnt) if (!reqcnt)
return -ENOMEM; return -ENOMEM;
zcrypt_perdev_reqcnt(reqcnt, AP_DEVICES); zcrypt_perdev_reqcnt(reqcnt, AP_DEVICES);
...@@ -1480,7 +1482,7 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd, ...@@ -1480,7 +1482,7 @@ static long zcrypt_unlocked_ioctl(struct file *filp, unsigned int cmd,
} }
case Z90STAT_PERDEV_REQCNT: { case Z90STAT_PERDEV_REQCNT: {
/* the old ioctl supports only 64 adapters */ /* the old ioctl supports only 64 adapters */
int reqcnt[MAX_ZDEV_CARDIDS]; u32 reqcnt[MAX_ZDEV_CARDIDS];
zcrypt_perdev_reqcnt(reqcnt, MAX_ZDEV_CARDIDS); zcrypt_perdev_reqcnt(reqcnt, MAX_ZDEV_CARDIDS);
if (copy_to_user((int __user *) arg, reqcnt, sizeof(reqcnt))) if (copy_to_user((int __user *) arg, reqcnt, sizeof(reqcnt)))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment