Skip to content

Commit b8ee323

Browse files
committed
info: print description
Signed-off-by: Pavel Boldin <pboldin@cloudlinux.com>
1 parent 67b0e8e commit b8ee323

2 files changed

Lines changed: 148 additions & 6 deletions

File tree

src/kpatch_user.c

Lines changed: 145 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ free_storage_patch_cb(struct rb_node *node)
132132
patch = rb_entry(node, struct kpatch_storage_patch, node);
133133
kpatch_close_file(&patch->kpfile);
134134

135+
free(patch->desc);
135136
free(patch);
136137
}
137138

@@ -368,6 +369,63 @@ storage_have_patch(kpatch_storage_t *storage, const char *buildid,
368369
return PATCH_FOUND;
369370
}
370371

372+
static char *
373+
storage_get_description(kpatch_storage_t *storage,
374+
struct kpatch_storage_patch *patch)
375+
{
376+
char *desc = NULL;
377+
char path[PATH_MAX];
378+
int fd, rv, alloc = 0, sz = 0;
379+
380+
if (!storage->is_patch_dir)
381+
return NULL;
382+
383+
if (patch->desc)
384+
return patch->desc;
385+
386+
sprintf(path, "%s/%d/description", patch->buildid, patch->patchlevel);
387+
fd = openat(storage->patch_fd, path, O_RDONLY);
388+
if (fd == -1)
389+
return NULL;
390+
391+
while (1) {
392+
if (sz + 1024 >= alloc) {
393+
char *olddesc = desc;
394+
alloc += PAGE_SIZE;
395+
396+
desc = malloc(alloc);
397+
398+
if (olddesc != NULL) {
399+
memcpy(desc, olddesc, sz);
400+
free(olddesc);
401+
}
402+
403+
olddesc = desc;
404+
}
405+
406+
rv = read(fd, desc + sz, alloc - sz);
407+
if (rv == -1 && errno == EINTR)
408+
continue;
409+
410+
if (rv == -1)
411+
goto err_free;
412+
413+
if (rv == 0)
414+
break;
415+
416+
sz += rv;
417+
}
418+
419+
patch->desc = desc;
420+
421+
return desc;
422+
423+
err_free:
424+
free(desc);
425+
close(fd);
426+
return NULL;
427+
}
428+
371429
static int
372430
storage_lookup_patches(kpatch_storage_t *storage, kpatch_process_t *proc)
373431
{
@@ -1353,6 +1411,7 @@ int usage_info(const char *err)
13531411
fprintf(stderr, "usage: libcare-ctl info [options] [-b BUILDID] [-p PID] [-s STORAGE] [-r REGEXP]\n");
13541412
fprintf(stderr, "\nOptions:\n");
13551413
fprintf(stderr, " -h - this message\n");
1414+
fprintf(stderr, " -n - don't print patch descriptions\n");
13561415
fprintf(stderr, " -b <BUILDID> - output all processes having object with specified BuildID loaded\n");
13571416
fprintf(stderr, " -p <PID> - target process, 'all' or omitted for all the system processes\n");
13581417
fprintf(stderr, " -s <STORAGE> - only show BuildIDs of object having patches in STORAGE, default %s\n",
@@ -1365,8 +1424,23 @@ struct info_data {
13651424
const char *buildid;
13661425
kpatch_storage_t *storage;
13671426
regex_t *name_re;
1427+
int print_description;
1428+
int may_update, vulnerable;
13681429
};
13691430

1431+
const char *RED = "\x1B[31m";
1432+
const char *GREEN = "\x1B[32m";
1433+
const char *YELLOW = "\x1B[33m";
1434+
const char *RESET = "\x1B[0m";
1435+
1436+
static void
1437+
init_colors(void)
1438+
{
1439+
if (!isatty(fileno(stdout))) {
1440+
RED = GREEN = YELLOW = RESET = "";
1441+
}
1442+
}
1443+
13701444
static int
13711445
object_info(struct info_data *data, struct object_file *o,
13721446
int *pid_printed)
@@ -1422,11 +1496,52 @@ object_info(struct info_data *data, struct object_file *o,
14221496
if (storage_patch_found(patch) && patch->patchlevel) {
14231497
printf(" latest=%d", patch->patchlevel);
14241498
}
1425-
if (patch && (o->applied_patch == NULL || patch->patchlevel > o->kpfile.patch->user_level)) {
1426-
printf("\nbetter patch available, do `libcare-client /run/libcare.sock update`");
1499+
1500+
/* empty patch patchlevel=0 with description of bugs in the version */
1501+
if (patch && patch->patchlevel == 0 && o->applied_patch == NULL) {
1502+
printf(" %sVULNERABLE%s\n", RED, RESET);
1503+
1504+
if (data->print_description) {
1505+
char *desc;
1506+
1507+
desc = storage_get_description(data->storage, patch);
1508+
printf("\n%sVULNERABLE VERSION:\n", RED);
1509+
1510+
printf("%s%s", desc, RESET);
1511+
}
1512+
1513+
data->vulnerable ++;
14271514
}
1515+
14281516
printf("\n");
14291517

1518+
/* Old or no patch applied but we have one in storage */
1519+
if (patch && patch->patchlevel != 0 &&
1520+
(o->applied_patch == NULL || patch->patchlevel > o->kpfile.patch->user_level)) {
1521+
if (data->print_description) {
1522+
char *desc;
1523+
1524+
printf("\n%snew patch description:\n", YELLOW);
1525+
1526+
desc = storage_get_description(data->storage, patch);
1527+
printf("%s%s", desc, RESET);
1528+
}
1529+
1530+
data->may_update++;
1531+
return 0;
1532+
}
1533+
1534+
/* patch applied and is latest version. show descripition for it */
1535+
if (patch && o->applied_patch != NULL && data->print_description) {
1536+
char *desc;
1537+
1538+
printf("\n%slatest patch applied\n", GREEN);
1539+
1540+
desc = storage_get_description(data->storage, patch);
1541+
printf("%s%s", desc, RESET);
1542+
return 0;
1543+
}
1544+
14301545
return 0;
14311546
}
14321547

@@ -1455,6 +1570,8 @@ process_info(int pid, void *_data)
14551570
if (object_info(data, o, &pid_printed))
14561571
break;
14571572

1573+
if (pid_printed && data->print_description)
1574+
printf("========================================\n");
14581575
out:
14591576
kpatch_process_free(proc);
14601577

@@ -1465,14 +1582,21 @@ static int
14651582
processes_info(int pid,
14661583
const char *buildid,
14671584
const char *storagepath,
1468-
const char *regexp)
1585+
const char *regexp,
1586+
int print_description)
14691587
{
14701588
int ret = -1;
14711589
struct info_data data = { 0, };
14721590
kpatch_storage_t storage;
14731591
regex_t regex;
14741592

1593+
init_colors();
1594+
14751595
data.buildid = buildid;
1596+
data.print_description = print_description;
1597+
data.may_update = 0;
1598+
data.vulnerable = 0;
1599+
14761600
if (regexp != NULL) {
14771601
ret = regcomp(&regex, regexp, REG_EXTENDED);
14781602
if (ret != 0) {
@@ -1491,6 +1615,17 @@ processes_info(int pid,
14911615

14921616
ret = processes_do(pid, process_info, &data);
14931617

1618+
if (data.vulnerable) {
1619+
printf("%s%d object(s) are vulnerable%s\n", RED, data.vulnerable, RESET);
1620+
}
1621+
1622+
if (data.may_update) {
1623+
printf("%s%d object(s) may be updated to the latest patch%s\n",
1624+
YELLOW, data.may_update, RESET);
1625+
printf("\n%sRun: libcare-client /run/libcare.sock update%s\n",
1626+
RED, RESET);
1627+
}
1628+
14941629
out_err:
14951630
if (data.storage != NULL) {
14961631
storage_free(data.storage);
@@ -1504,12 +1639,12 @@ processes_info(int pid,
15041639

15051640
int cmd_info_user(int argc, char *argv[])
15061641
{
1507-
int opt, pid = -1, verbose = 0;
1642+
int opt, pid = -1, verbose = 0, print_description = 1;
15081643
const char *buildid = NULL;
15091644
const char *storagepath = storage_dir;
15101645
const char *regexp = NULL;
15111646

1512-
while ((opt = getopt(argc, argv, "hb:p:s:r:v")) != EOF) {
1647+
while ((opt = getopt(argc, argv, "hb:p:s:r:vn")) != EOF) {
15131648
switch (opt) {
15141649
case 'b':
15151650
buildid = optarg;
@@ -1524,6 +1659,9 @@ int cmd_info_user(int argc, char *argv[])
15241659
!strcmp(storagepath, "/dev/null"))
15251660
storagepath = NULL;
15261661
break;
1662+
case 'n':
1663+
print_description = 0;
1664+
break;
15271665
case 'r':
15281666
regexp = optarg;
15291667
break;
@@ -1546,7 +1684,8 @@ int cmd_info_user(int argc, char *argv[])
15461684
}
15471685

15481686

1549-
return processes_info(pid, buildid, storagepath, regexp);
1687+
return processes_info(pid, buildid, storagepath, regexp,
1688+
print_description);
15501689
}
15511690

15521691

src/kpatch_user.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ struct kpatch_storage_patch {
1515
/* Patch level */
1616
int patchlevel;
1717

18+
/* Description cache */
19+
char *desc;
20+
1821
/* Node for rb_root */
1922
struct rb_node node;
2023
};

0 commit comments

Comments
 (0)