Skip to content

Commit fb4cd74

Browse files
author
Roman Rashchupkin
committed
Add error return codes to libcare-ctl.
1 parent 9752ec3 commit fb4cd74

File tree

5 files changed

+88
-50
lines changed

5 files changed

+88
-50
lines changed

src/kpatch_log.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,11 @@ void kpfatal(const char *fmt, ...)
5252
__valog(LOG_ERR, "FATAL! ", fmt, va);
5353
va_end(va);
5454

55-
exit(1);
55+
#ifdef STRESS_TEST
56+
if (parent_pid >= 0)
57+
stress_test_notify_parent();
58+
#endif
59+
exit(ERROR_FATAL);
5660
}
5761

5862
extern int elf_errno(void) __attribute__((weak));
@@ -98,5 +102,5 @@ void _kpfatalerror(const char *file, int line, const char *fmt, ...)
98102
__valogerror(file, line, fmt, va);
99103
va_end(va);
100104

101-
exit(EXIT_FAILURE);
105+
exit(ERROR_FATAL);
102106
}

src/kpatch_log.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,18 @@
33

44
#include <stdio.h>
55

6+
#define ERROR_SUCCESS 0 // exit code 0
7+
#define ERROR_GENERAL -255 // exit code 1
8+
#define ERROR_FATAL -254 // exit code 2
9+
#define ERROR_ARGUMENTS -253 // exit code 3
10+
#define ERROR_NOPROCESS -252 // exit code 4
11+
#define ERROR_NOPATCH -251 // exit code 5
12+
#define ERROR_PATCH -250 // exit code 6
13+
#define ERROR_UNPATCH -249 // exit code 7
14+
#define ERROR_PATCH_UNPATCH -248 // exit code 8
15+
#define ERROR_ACCESS -247 // exit code 9
16+
#define ERROR_BUSY -246 // exit code 10
17+
618
extern int log_level, log_indent;
719

820
void kplog(int level, const char *fmt, ...) __attribute__((format(printf, 2, 3)));

src/kpatch_patch.c

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -256,15 +256,18 @@ patch_ensure_safety(struct object_file *o,
256256
ret = kpatch_ptrace_execute_until(o->proc, 3000, 0);
257257

258258
/* OK, at this point we may have new threads, discover them */
259-
if (ret == 0)
259+
if (ret == 0) {
260260
ret = kpatch_process_attach(o->proc);
261+
if (ret == ERROR_ACCESS)
262+
return ret;
263+
}
261264
if (ret == 0)
262265
ret = patch_verify_safety(o, NULL, action);
263266
}
264267

265268
free(retips);
266269

267-
return ret ? -1 : 0;
270+
return ret ? ERROR_BUSY : 0;
268271
}
269272

270273
/*****************************************************************************
@@ -347,12 +350,12 @@ object_apply_patch(struct object_file *o)
347350
ret = duplicate_kp_file(o);
348351
if (ret < 0) {
349352
kplogerror("can't duplicate kp_file\n");
350-
return -1;
353+
return ERROR_PATCH;
351354
}
352355

353356
ret = kpatch_elf_load_kpatch_info(o);
354357
if (ret < 0)
355-
return ret;
358+
return ERROR_PATCH;
356359

357360
kp = o->kpfile.patch;
358361

@@ -379,26 +382,26 @@ object_apply_patch(struct object_file *o)
379382
*/
380383
ret = kpatch_object_allocate_patch(o, sz);
381384
if (ret < 0)
382-
return ret;
385+
return ERROR_PATCH;
383386
ret = kpatch_resolve(o);
384387
if (ret < 0)
385-
return ret;
388+
return ERROR_PATCH;
386389
ret = kpatch_relocate(o);
387390
if (ret < 0)
388-
return ret;
391+
return ERROR_PATCH;
389392
ret = kpatch_process_mem_write(o->proc,
390393
kp,
391394
o->kpta,
392395
kp->total_size);
393396
if (ret < 0)
394-
return -1;
397+
return ERROR_PATCH;
395398
if (o->jmp_table) {
396399
ret = kpatch_process_mem_write(o->proc,
397400
o->jmp_table,
398401
o->kpta + kp->jmp_offset,
399402
o->jmp_table->size);
400403
if (ret < 0)
401-
return ret;
404+
return ERROR_PATCH;
402405
}
403406

404407
ret = patch_ensure_safety(o, ACTION_APPLY_PATCH);
@@ -408,7 +411,7 @@ object_apply_patch(struct object_file *o)
408411
for (i = 0; i < o->ninfo; i++) {
409412
ret = patch_apply_hunk(o, i);
410413
if (ret < 0)
411-
return ret;
414+
return ERROR_PATCH;
412415
}
413416

414417
return 1;
@@ -442,9 +445,10 @@ object_unapply_old_patch(struct object_file *o)
442445
kpatch_applied->user_level,
443446
kpatch_storage->user_level);
444447
ret = object_unapply_patch(o, /* check_flag */ 0);
445-
if (ret < 0)
448+
if (ret < 0) {
446449
kperr("can't unapply patch for %s\n", o->name);
447-
else {
450+
ret = ERROR_UNPATCH;
451+
} else {
448452
/* TODO(pboldin): handle joining the holes here */
449453
o->applied_patch = NULL;
450454
o->info = NULL;
@@ -464,7 +468,7 @@ kpatch_apply_patches(kpatch_process_t *proc)
464468

465469
ret = object_unapply_old_patch(o);
466470
if (ret < 0)
467-
break;
471+
return ret;
468472

469473
ret = object_apply_patch(o);
470474
if (ret < 0)
@@ -480,11 +484,11 @@ kpatch_apply_patches(kpatch_process_t *proc)
480484
* TODO(pboldin): close the holes so the state is the same
481485
* after unpatch
482486
*/
483-
ret = object_unapply_patch(o, /* check_flag */ 1);
484-
if (ret < 0) {
487+
if (object_unapply_patch(o, /* check_flag */ 1) < 0) {
488+
ret = ERROR_PATCH_UNPATCH;
485489
kperr("Can't unapply patch for %s\n", o->name);
486490
}
487-
return -1;
491+
return ret;
488492
}
489493

490494
int process_patch(int pid, void *_data)
@@ -565,16 +569,18 @@ int process_patch(int pid, void *_data)
565569

566570
out:
567571
if (ret < 0) {
568-
printf("Failed to apply patch '%s'\n", storage->path);
572+
if (ret == -1)
573+
return ERROR_PATCH;
574+
kpinfo("Failed to apply patch '%s'\n", storage->path);
569575
kperr("Failed to apply patch '%s'\n", storage->path);
570-
} else if (ret == 0)
571-
printf("No patch(es) applicable to PID '%d' have been found\n", pid);
572-
else {
573-
printf("%d patch hunk(s) have been successfully applied to PID '%d'\n", ret, pid);
574-
ret = 0;
576+
return ret;
577+
} else if (ret == 0) {
578+
kpinfo("No patch(es) applicable to PID '%d' have been found\n", pid);
579+
return ERROR_NOPATCH;
580+
} else {
581+
kpinfo("%d patch hunk(s) have been successfully applied to PID '%d'\n", ret, pid);
582+
return ERROR_SUCCESS;
575583
}
576-
577-
return ret;
578584
}
579585

580586

@@ -592,6 +598,8 @@ object_find_applied_patch_info(struct object_file *o)
592598

593599
if (o->info != NULL)
594600
return 0;
601+
if (!o->kpta || !o->kpfile.patch)
602+
return -1;
595603

596604
iter = kpatch_process_mem_iter_init(o->proc);
597605
if (iter == NULL)
@@ -617,6 +625,8 @@ object_find_applied_patch_info(struct object_file *o)
617625
o->ninfo++;
618626
} while (1);
619627

628+
if (!o->applied_patch)
629+
return 0;
620630
o->applied_patch->info = o->info;
621631
o->applied_patch->ninfo = o->ninfo;
622632

@@ -641,6 +651,8 @@ object_unapply_patch(struct object_file *o, int check_flag)
641651
if (ret < 0)
642652
return ret;
643653

654+
if (!o->kpta || !o->kpfile.patch)
655+
return -1;
644656
orig_code_addr = o->kpta + o->kpfile.patch->user_undo;
645657

646658
for (i = 0; i < o->ninfo; i++) {
@@ -728,7 +740,7 @@ int process_unpatch(int pid, void *_data)
728740

729741
ret = kpatch_process_init(proc, pid, /* start */ 0, /* send_fd */ -1);
730742
if (ret < 0)
731-
return -1;
743+
return ret;
732744

733745
kpatch_process_print_short(proc);
734746

@@ -749,13 +761,17 @@ int process_unpatch(int pid, void *_data)
749761
out:
750762
kpatch_process_free(proc);
751763

752-
if (ret < 0)
753-
printf("Failed to cancel patches for %d\n", pid);
754-
else if (ret == 0)
755-
printf("No patch(es) cancellable from PID '%d' were found\n", pid);
756-
else
757-
printf("%d patch hunk(s) were successfully cancelled from PID '%d'\n", ret, pid);
758-
759-
return ret;
764+
if (ret < 0) {
765+
kpinfo("Failed to cancel patches for %d\n", pid);
766+
if (ret == -1)
767+
return ERROR_UNPATCH;
768+
return ret;
769+
} else if (ret == 0) {
770+
kpinfo("No patch(es) cancellable from PID '%d' were found\n", pid);
771+
return ERROR_NOPATCH;
772+
} else {
773+
kpinfo("%d patch hunk(s) were successfully cancelled from PID '%d'\n", ret, pid);
774+
return 0;
775+
}
760776
}
761777

src/kpatch_process.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -630,7 +630,7 @@ kpatch_process_mem_open(kpatch_process_t *proc, int mode)
630630
proc->memfd = open(path, mode == MEM_WRITE ? O_RDWR : O_RDONLY);
631631
if (proc->memfd < 0) {
632632
kplogerror("can't open /proc/%d/mem", proc->pid);
633-
return -1;
633+
return ERROR_NOPROCESS;
634634
}
635635

636636
return 0;
@@ -643,7 +643,7 @@ kpatch_process_attach(kpatch_process_t *proc)
643643
size_t i, npids = 0, alloc = 0, prevnpids = 0, nattempts;
644644

645645
if (kpatch_process_mem_open(proc, MEM_WRITE) < 0)
646-
return -1;
646+
return ERROR_ACCESS;
647647

648648
for (nattempts = 0; nattempts < max_attach_attempts; nattempts++) {
649649
ret = process_list_threads(proc, &pids, &npids, &alloc);
@@ -713,7 +713,7 @@ kpatch_process_attach(kpatch_process_t *proc)
713713
process_detach(proc);
714714
dealloc:
715715
free(pids);
716-
return -1;
716+
return ERROR_ACCESS;
717717
}
718718

719719
static void
@@ -890,7 +890,7 @@ kpatch_process_load_libraries(kpatch_process_t *proc)
890890
ret = kpatch_process_attach(proc);
891891
if (ret < 0) {
892892
kperr("unable to attach to just started process\n");
893-
return -1;
893+
return ret;
894894
}
895895

896896
if (proc->send_fd != -1) {
@@ -1131,7 +1131,7 @@ kpatch_process_init(kpatch_process_t *proc,
11311131
out_unlock:
11321132
unlock_process(pid, fdmaps);
11331133
out_err:
1134-
return -1;
1134+
return ERROR_NOPROCESS;
11351135
}
11361136

11371137
void

src/kpatch_user.c

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ static int usage_patch(const char *err)
6868
fprintf(stderr, "\nOptions:\n");
6969
fprintf(stderr, " -h - this message\n");
7070
fprintf(stderr, " -p <PID> - target process\n");
71-
return err ? 0 : -1;
71+
return err ? 0 : ERROR_ARGUMENTS;
7272
}
7373

7474
static int
@@ -80,7 +80,7 @@ patch_user(const char *storage_path, int pid,
8080

8181
ret = storage_init(&storage, storage_path);
8282
if (ret < 0)
83-
return ret;
83+
return ERROR_NOPATCH;
8484

8585
ret = processes_patch(&storage, pid, is_just_started, send_fd);
8686

@@ -337,7 +337,7 @@ process_info(int pid, void *_data)
337337

338338
ret = kpatch_process_init(proc, pid, /* start */ 0, /* send_fd */ -1);
339339
if (ret < 0)
340-
return -1;
340+
return ret;
341341

342342
ret = kpatch_process_mem_open(proc, MEM_READ);
343343
if (ret < 0)
@@ -640,8 +640,12 @@ static int cmd_stress_test(int fd, int argc, char *argv[])
640640

641641
static int usage_stresstest()
642642
{
643-
fprintf(stderr, "usage: libcare-stresstest PERIOD(ms, 0 - only patch) <UNIX socket> [STORAGE ROOT]\n");
644-
return -1;
643+
fprintf(stderr, "usage: libcare-stresstest [args] PERIOD(ms, 0 - only patch) <UNIX socket> [STORAGE ROOT]\n");
644+
fprintf(stderr, "\nOptions:\n");
645+
fprintf(stderr, " -v - verbose mode\n");
646+
fprintf(stderr, " -l <BASE> - log file name <BASE>-PID\n");
647+
fprintf(stderr, " -h - this message\n");
648+
return ERROR_ARGUMENTS;
645649
}
646650

647651
#endif
@@ -745,7 +749,7 @@ static int usage_server(const char *err)
745749
if (err)
746750
fprintf(stderr, "err: %s\n", err);
747751
fprintf(stderr, "usage: libcare-ctl server <UNIX socket> [STORAGE ROOT]\n");
748-
return -1;
752+
return ERROR_ARGUMENTS;
749753
}
750754

751755
#define LISTEN_BACKLOG 1
@@ -904,9 +908,11 @@ processes_do(int pid, callback_t callback, void *data)
904908

905909
rv = callback(pid, data);
906910
if (rv < 0)
907-
ret = -1;
908-
if (rv == -2)
911+
ret = rv;
912+
if (rv == -2) {
913+
ret = ERROR_GENERAL;
909914
break;
915+
}
910916
}
911917

912918
closedir(dir);
@@ -930,7 +936,7 @@ static int usage(const char *err)
930936
fprintf(stderr, " unpatch- unapply patch from a user-space process\n");
931937
fprintf(stderr, " info - show info on applied patches\n");
932938
fprintf(stderr, " server - listen on a unix socket for commands\n");
933-
return -1;
939+
return ERROR_ARGUMENTS;
934940
}
935941

936942
static int
@@ -960,7 +966,7 @@ int main(int argc, char *argv[])
960966
log_level += 1;
961967
break;
962968
case 'h':
963-
return usage(NULL);
969+
return usage(ERROR_SUCCESS);
964970
default:
965971
return usage("unknown option");
966972
}

0 commit comments

Comments
 (0)