Coverage Report

Created: 2026-07-26 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pam_ipmi_fuzzer.c
Line
Count
Source
1
/*
2
 * Copyright 2026 Google LLC
3
 *
4
 * Licensed under the Apache License, Version 2.0 (the "License");
5
 * you may not use this file except in compliance with the License.
6
 * You may obtain a copy of the License at
7
 *
8
 *      http://www.apache.org/licenses/LICENSE-2.0
9
 *
10
 * Unless required by applicable law or agreed to in writing, software
11
 * distributed under the License is distributed on an "AS IS" BASIS,
12
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 * See the License for the specific language governing permissions and
14
 * limitations under the License.
15
 */
16
17
#include <stdint.h>
18
#include <stddef.h>
19
#include <stdlib.h>
20
#include <string.h>
21
#include <unistd.h>
22
#include <stdio.h>
23
24
#include <security/pam_modules.h>
25
#include <security/pam_ext.h>
26
27
// Mocking some functions that might be problematic
28
0
int lckpwdf(void) { return 0; }
29
0
int ulckpwdf(void) { return 0; }
30
31
// The function we want to fuzz
32
int update_pass_special_file(const pam_handle_t *pamh, const char *keyfilename,
33
           const char *filename, const char *forwho,
34
           const char *towhat);
35
36
2
int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
37
2
    if (size < 10) return 0;
38
39
2
    char key_file[] = "/tmp/fuzz_key_XXXXXX";
40
2
    int key_fd = mkstemp(key_file);
41
2
    if (key_fd == -1) return 0;
42
    // key file must be 8 bytes as per pam_ipmisave.c: MAX_KEY_SIZE
43
2
    uint8_t key_data[8] = {0};
44
2
    if (size >= 8) {
45
2
        memcpy(key_data, data, 8);
46
2
        data += 8;
47
2
        size -= 8;
48
2
    }
49
2
    write(key_fd, key_data, 8);
50
2
    close(key_fd);
51
52
2
    char pass_file[] = "/tmp/fuzz_pass_XXXXXX";
53
2
    int pass_fd = mkstemp(pass_file);
54
2
    if (pass_fd == -1) {
55
0
        unlink(key_file);
56
0
        return 0;
57
0
    }
58
2
    if (size > 0) {
59
        // Use half of remaining data for the initial pass file content
60
2
        size_t initial_file_size = size / 2;
61
2
        write(pass_fd, data, initial_file_size);
62
2
        data += initial_file_size;
63
2
        size -= initial_file_size;
64
2
    }
65
2
    close(pass_fd);
66
67
2
    if (size < 2) {
68
0
        unlink(key_file);
69
0
        unlink(pass_file);
70
0
        return 0;
71
0
    }
72
73
    // Use the rest for username and password
74
2
    size_t user_len = size / 2;
75
2
    char *user = malloc(user_len + 1);
76
2
    memcpy(user, data, user_len);
77
2
    user[user_len] = '\0';
78
2
    data += user_len;
79
2
    size -= user_len;
80
81
2
    char *pass = malloc(size + 1);
82
2
    memcpy(pass, data, size);
83
2
    pass[size] = '\0';
84
85
    // Call the function
86
2
    update_pass_special_file(NULL, key_file, pass_file, user, pass);
87
88
2
    free(user);
89
2
    free(pass);
90
2
    unlink(key_file);
91
2
    unlink(pass_file);
92
93
2
    return 0;
94
2
}