Changeset 160


Ignore:
Timestamp:
Dec 16, 2008, 4:18:05 AM (17 years ago)
Author:
Paul Smedley
Message:

New implementation of os2_randget() - fixes SIGSEGV with GCC 4.3.2 and -O2 or higher

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/samba-3.0/source/lib/os2ea.c

    r56 r160  
    3131#define PRINTF_ATTRIBUTE(a1, a2) __attribute__ ((format (__printf__, a1, a2)))
    3232#define CMD_KI_RDCNT            (0x63)
    33 
    34 typedef struct _CPUUTIL {
    35     ULONG ulTimeLow;     /* Low 32 bits of time stamp      */
    36     ULONG ulTimeHigh;    /* High 32 bits of time stamp     */
    37     ULONG ulIdleLow;     /* Low 32 bits of idle time       */
    38     ULONG ulIdleHigh;    /* High 32 bits of idle time      */
    39     ULONG ulBusyLow;     /* Low 32 bits of busy time       */
    40     ULONG ulBusyHigh;    /* High 32 bits of busy time      */
    41     ULONG ulIntrLow;     /* Low 32 bits of interrupt time  */
    42     ULONG ulIntrHigh;    /* High 32 bits of interrupt time */
    43    } CPUUTIL;
    4433
    4534#include "local.h"
     
    10897}
    10998
    110 // very simple random data gatherer derived from openssl
     99/* Functions below are based on APR random code */
     100/* Licensed to the Apache Software Foundation (ASF) under one or more
     101 * contributor license agreements.  See the NOTICE file distributed with
     102 * this work for additional information regarding copyright ownership.
     103 * The ASF licenses this file to You under the Apache License, Version 2.0
     104 * (the "License"); you may not use this file except in compliance with
     105 * the License.  You may obtain a copy of the License at
     106 *
     107 *     http://www.apache.org/licenses/LICENSE-2.0
     108 *
     109 * Unless required by applicable law or agreed to in writing, software
     110 * distributed under the License is distributed on an "AS IS" BASIS,
     111 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     112 * See the License for the specific language governing permissions and
     113 * limitations under the License.
     114 */
     115
     116/* The high resolution timer API provides access to the hardware timer
     117 * running at around 1.1MHz. The amount this changes in a time slice is
     118 * varies randomly due to system events, hardware interrupts etc
     119 */
     120
    111121void os2_randget(char * buffer, int length)
    112122{
    113         QWORD qwTime;
    114         ULONG SysVars[QSV_FOREGROUND_PROCESS];
    115         int done = 0;
    116 
    117         if (!buffer || length <= 0)
    118         {
    119                 return;
    120         }
    121 
    122         DosTmrQueryTime(&qwTime);
    123         memcpy(buffer, &qwTime, sizeof(qwTime) > length ? length : sizeof(qwTime));
    124         done += sizeof(qwTime);
    125         if (done >= length)
    126         {
    127                 return;
    128         }
    129 
    130         if (DosPerfSysCall)
    131         {
    132                 CPUUTIL util;
    133                 if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0)
    134                 {
    135                         memcpy(buffer + done, &util, sizeof(util) > length - done ? length - done : sizeof(util));
    136                         done += sizeof(util);
    137                         if (done >= length)
    138                         {
    139                                 return;
    140                         }
    141                 }
    142         }
    143 
    144         DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars));
    145         memcpy(buffer + done, SysVars, sizeof(SysVars) > length - done ? length - done : sizeof(SysVars));
     123    UCHAR randbyte();
     124    unsigned int idx;
     125
     126    for (idx=0; idx<length; idx++)
     127        buffer[idx] = randbyte();
     128
     129}
     130
     131static UCHAR randbyte_hrtimer()
     132{
     133    QWORD t1, t2;
     134    UCHAR byte;
     135
     136    DosTmrQueryTime(&t1);
     137    DosSleep(5);
     138    DosTmrQueryTime(&t2);
     139
     140    byte = (t2.ulLo - t1.ulLo) & 0xFF;
     141    byte ^= (t2.ulLo - t1.ulLo) >> 8;
     142    return byte;
     143}
     144
     145
     146
     147/* A bunch of system information like memory & process stats.
     148 * Not highly random but every bit helps....
     149 */
     150static UCHAR randbyte_sysinfo()
     151{
     152    UCHAR byte = 0;
     153    UCHAR SysVars[100];
     154    int b;
     155
     156    DosQuerySysInfo(1, QSV_FOREGROUND_PROCESS, SysVars, sizeof(SysVars));
     157
     158    for (b = 0; b < 100; b++) {
     159        byte ^= SysVars[b];
     160    }
     161
     162    return byte;
     163}
     164
     165
     166
     167/* Similar in concept to randbyte_hrtimer() but accesses the CPU's internal
     168 * counters which run at the CPU's MHz speed. We get separate
     169 * idle / busy / interrupt cycle counts which should provide very good
     170 * randomness due to interference of hardware events.
     171 * This only works on newer CPUs (at least PPro or K6) and newer OS/2 versions
     172 * which is why it's run-time linked.
     173 */
     174
     175static HMODULE hDoscalls = 0;
     176#define   CMD_KI_RDCNT    (0x63)
     177
     178typedef struct _CPUUTIL {
     179    ULONG ulTimeLow;            /* Low 32 bits of time stamp      */
     180    ULONG ulTimeHigh;           /* High 32 bits of time stamp     */
     181    ULONG ulIdleLow;            /* Low 32 bits of idle time       */
     182    ULONG ulIdleHigh;           /* High 32 bits of idle time      */
     183    ULONG ulBusyLow;            /* Low 32 bits of busy time       */
     184    ULONG ulBusyHigh;           /* High 32 bits of busy time      */
     185    ULONG ulIntrLow;            /* Low 32 bits of interrupt time  */
     186    ULONG ulIntrHigh;           /* High 32 bits of interrupt time */
     187} CPUUTIL;
     188
     189
     190static UCHAR randbyte_perf()
     191{
     192    UCHAR byte = 0;
     193    CPUUTIL util;
     194    int c;
     195
     196#ifndef __INNOTEK_LIBC__
     197    if (hDoscalls == 0) {
     198        char failed_module[20];
     199        ULONG rc;
     200
     201        rc = DosLoadModule(failed_module, sizeof(failed_module), "DOSCALLS",
     202                           &hDoscalls);
     203
     204        if (rc == 0) {
     205            rc = DosQueryProcAddr(hDoscalls, 976, NULL, (PFN *)&DosPerfSysCall);
     206
     207            if (rc) {
     208                DosPerfSysCall = NULL;
     209            }
     210        }
     211    }
     212
     213    if (DosPerfSysCall) {
     214        if (DosPerfSysCall(CMD_KI_RDCNT, (ULONG)&util, 0, 0) == 0) {
     215            for (c = 0; c < sizeof(util); c++) {
     216                byte ^= ((UCHAR *)&util)[c];
     217            }
     218        }
     219        else {
     220            DosPerfSysCall = NULL;
     221        }
     222    }
     223#endif
     224    return byte;
     225}
     226
     227
     228
     229UCHAR randbyte()
     230{
     231    return randbyte_hrtimer() ^ randbyte_sysinfo() ^ randbyte_perf();
    146232}
    147233
Note: See TracChangeset for help on using the changeset viewer.